Files
wehub-resource-sync ee3943b5b1
CI / test (deps-minimum, windows-latest, unit) (push) Blocked by required conditions
CI / test_py314 (deps-latest, ubuntu-latest, unit) (push) Blocked by required conditions
CI / test_py314 (deps-latest, windows-latest, unit) (push) Blocked by required conditions
CI / test_py314_future (deps-latest, ubuntu-latest, unit) (push) Blocked by required conditions
CI / test_py314_future (deps-latest, windows-latest, unit) (push) Blocked by required conditions
Secret Leaks / trufflehog (push) Waiting to run
CI / check_code_quality (push) Waiting to run
CI / test (deps-latest, ubuntu-latest, integration) (push) Blocked by required conditions
CI / test (deps-latest, ubuntu-latest, unit) (push) Blocked by required conditions
CI / test (deps-latest, windows-latest, integration) (push) Blocked by required conditions
CI / test (deps-latest, windows-latest, unit) (push) Blocked by required conditions
CI / test (deps-minimum, ubuntu-latest, integration) (push) Blocked by required conditions
CI / test (deps-minimum, ubuntu-latest, unit) (push) Blocked by required conditions
CI / test (deps-minimum, windows-latest, integration) (push) Blocked by required conditions
Build documentation / build (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 13:24:32 +08:00

820 lines
32 KiB
Python

import os
import tarfile
from itertools import product
from pathlib import Path
import numpy as np
import pyarrow as pa
import pytest
from datasets import Column, Dataset, concatenate_datasets, load_dataset
from datasets.features import Audio, Features, List, Value
from ..utils import require_torchcodec
@pytest.fixture()
def tar_wav_path(shared_datadir, tmp_path_factory):
audio_path = str(shared_datadir / "test_audio_44100.wav")
path = tmp_path_factory.mktemp("data") / "audio_data.wav.tar"
with tarfile.TarFile(path, "w") as f:
f.add(audio_path, arcname=os.path.basename(audio_path))
return path
@pytest.fixture()
def tar_mp3_path(shared_datadir, tmp_path_factory):
audio_path = str(shared_datadir / "test_audio_44100.mp3")
path = tmp_path_factory.mktemp("data") / "audio_data.mp3.tar"
with tarfile.TarFile(path, "w") as f:
f.add(audio_path, arcname=os.path.basename(audio_path))
return path
def iter_archive(archive_path):
with tarfile.open(archive_path) as tar:
for tarinfo in tar:
file_path = tarinfo.name
file_obj = tar.extractfile(tarinfo)
yield file_path, file_obj
def test_audio_instantiation():
audio = Audio()
assert audio.sampling_rate is None
assert audio.id is None
assert audio.stream_index is None
assert audio.dtype == "dict"
assert audio.pa_type == pa.struct({"bytes": pa.binary(), "path": pa.string()})
assert audio._type == "Audio"
def test_audio_feature_type_to_arrow():
features = Features({"audio": Audio()})
assert features.arrow_schema == pa.schema({"audio": Audio().pa_type})
features = Features({"struct_containing_an_audio": {"audio": Audio()}})
assert features.arrow_schema == pa.schema({"struct_containing_an_audio": pa.struct({"audio": Audio().pa_type})})
features = Features({"sequence_of_audios": List(Audio())})
assert features.arrow_schema == pa.schema({"sequence_of_audios": pa.list_(Audio().pa_type)})
@require_torchcodec
@pytest.mark.parametrize(
"build_example",
[
lambda audio_path: audio_path,
lambda audio_path: Path(audio_path),
lambda audio_path: open(audio_path, "rb").read(),
lambda audio_path: {"path": audio_path},
lambda audio_path: {"path": audio_path, "bytes": None},
lambda audio_path: {"path": audio_path, "bytes": open(audio_path, "rb").read()},
lambda audio_path: {"path": None, "bytes": open(audio_path, "rb").read()},
lambda audio_path: {"bytes": open(audio_path, "rb").read()},
lambda audio_path: {"array": np.array([0.1, 0.2, 0.3]), "sampling_rate": 16_000},
],
)
def test_audio_feature_encode_example(shared_datadir, build_example):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
audio = Audio()
encoded_example = audio.encode_example(build_example(audio_path))
assert isinstance(encoded_example, dict)
assert encoded_example.keys() == {"bytes", "path"}
assert encoded_example["bytes"] is not None or encoded_example["path"] is not None
decoded_example = audio.decode_example(encoded_example)
assert isinstance(decoded_example, AudioDecoder)
@require_torchcodec
@pytest.mark.parametrize(
"build_example",
[
lambda audio_path: {"path": audio_path, "sampling_rate": 16_000},
lambda audio_path: {"path": audio_path, "bytes": None, "sampling_rate": 16_000},
lambda audio_path: {"path": audio_path, "bytes": open(audio_path, "rb").read(), "sampling_rate": 16_000},
lambda audio_path: {"array": np.array([0.1, 0.2, 0.3]), "sampling_rate": 16_000},
],
)
def test_audio_feature_encode_example_pcm(shared_datadir, build_example):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_16000.pcm")
audio = Audio(sampling_rate=16_000)
encoded_example = audio.encode_example(build_example(audio_path))
assert isinstance(encoded_example, dict)
assert encoded_example.keys() == {"bytes", "path"}
assert encoded_example["bytes"] is not None or encoded_example["path"] is not None
decoded_example = audio.decode_example(encoded_example)
assert isinstance(decoded_example, AudioDecoder)
sample_rates = [16_000, 48_000]
@require_torchcodec
@pytest.mark.parametrize(
"in_sample_rate,out_sample_rate",
list(product(sample_rates, sample_rates)),
)
def test_audio_feature_encode_example_audiodecoder(shared_datadir, in_sample_rate, out_sample_rate):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
audio = Audio(sampling_rate=out_sample_rate)
example = AudioDecoder(audio_path, sample_rate=in_sample_rate)
encoded_example = audio.encode_example(example)
assert isinstance(encoded_example, dict)
assert encoded_example.keys() == {"bytes", "path"}
assert encoded_example["bytes"] is not None or encoded_example["path"] is not None
decoded_example = audio.decode_example(encoded_example)
assert isinstance(decoded_example, AudioDecoder)
@require_torchcodec
def test_audio_decode_example(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
audio = Audio()
decoded_example = audio.decode_example(audio.encode_example(audio_path))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
with pytest.raises(RuntimeError):
Audio(decode=False).decode_example(audio_path)
@require_torchcodec
def test_audio_resampling(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
audio = Audio(sampling_rate=16000)
decoded_example = audio.decode_example(audio.encode_example(audio_path))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 73401)
@require_torchcodec
def test_audio_decode_example_mp3(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.mp3")
audio = Audio()
decoded_example = audio.decode_example(audio.encode_example(audio_path))
print("decoded_example", decoded_example)
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 110592)
@require_torchcodec
def test_audio_decode_example_opus(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_48000.opus")
audio = Audio()
decoded_example = audio.decode_example(audio.encode_example(audio_path))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == 48000
assert samples.data.shape == (1, 48000)
@require_torchcodec
@pytest.mark.parametrize("sampling_rate", [16_000, 48_000])
def test_audio_decode_example_pcm(shared_datadir, sampling_rate):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_16000.pcm")
audio_input = {"path": audio_path, "sampling_rate": 16_000}
audio = Audio(sampling_rate=sampling_rate)
decoded_example = audio.decode_example(audio.encode_example(audio_input))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == sampling_rate
assert samples.data.shape == (1, 16208 * sampling_rate // 16_000)
@require_torchcodec
def test_audio_resampling_mp3_different_sampling_rates(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.mp3")
audio_path2 = str(shared_datadir / "test_audio_16000.mp3")
audio = Audio(sampling_rate=48000)
decoded_example = audio.decode_example(audio.encode_example(audio_path))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == 48000
assert samples.data.shape == (2, 120373)
decoded_example = audio.decode_example(audio.encode_example(audio_path2))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == 48000
assert samples.data.shape == (2, 122688)
@require_torchcodec
def test_backwards_compatibility(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.mp3")
audio_path2 = str(shared_datadir / "test_audio_16000.mp3")
audio = Audio(sampling_rate=48000)
decoded_example = audio.decode_example(audio.encode_example(audio_path))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert decoded_example["sampling_rate"] == samples.sample_rate
assert decoded_example["array"].ndim == 1 # mono
assert abs(decoded_example["array"].shape[0] - samples.data.shape[1]) < 2 # can have off by one error
decoded_example = audio.decode_example(audio.encode_example(audio_path2))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert decoded_example["sampling_rate"] == samples.sample_rate
assert decoded_example["array"].ndim == 1 # mono
assert abs(decoded_example["array"].shape[0] - samples.data.shape[1]) < 2 # can have off by one error
@require_torchcodec
def test_dataset_with_audio_feature(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path]}
features = Features({"audio": Audio()})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
column = dset["audio"]
assert len(column) == 1
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
@require_torchcodec
def test_dataset_with_audio_feature_tar_wav(tar_wav_path):
from torchcodec.decoders import AudioDecoder
audio_filename = "test_audio_44100.wav"
data = {"audio": []}
for file_path, file_obj in iter_archive(tar_wav_path):
data["audio"].append({"path": file_path, "bytes": file_obj.read()})
break
features = Features({"audio": Audio()})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
assert item["audio"].metadata.path == audio_filename
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
assert batch["audio"][0].metadata.path == audio_filename
column = dset["audio"]
assert len(column) == 1
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
@require_torchcodec
def test_dataset_with_audio_feature_tar_mp3(tar_mp3_path):
from torchcodec.decoders import AudioDecoder
audio_filename = "test_audio_44100.mp3"
data = {"audio": []}
for file_path, file_obj in iter_archive(tar_mp3_path):
data["audio"].append({"path": file_path, "bytes": file_obj.read()})
break
features = Features({"audio": Audio()})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 110592)
assert item["audio"].metadata.path == audio_filename
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 110592)
assert batch["audio"][0].metadata.path == audio_filename
column = dset["audio"]
assert len(column) == 1
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 110592)
@require_torchcodec
def test_dataset_with_audio_feature_with_none():
data = {"audio": [None]}
features = Features({"audio": Audio()})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"audio"}
assert item["audio"] is None
batch = dset[:1]
assert len(batch) == 1
assert batch.keys() == {"audio"}
assert isinstance(batch["audio"], list) and all(item is None for item in batch["audio"])
column = dset["audio"]
assert len(column) == 1
assert isinstance(column, Column) and all(item is None for item in column)
# nested tests
data = {"audio": [[None]]}
features = Features({"audio": List(Audio())})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"audio"}
assert all(i is None for i in item["audio"])
data = {"nested": [{"audio": None}]}
features = Features({"nested": {"audio": Audio()}})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"nested"}
assert item["nested"].keys() == {"audio"}
assert item["nested"]["audio"] is None
@require_torchcodec
def test_resampling_at_loading_dataset_with_audio_feature(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path]}
features = Features({"audio": Audio(sampling_rate=16000)})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 73401)
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 73401)
column = dset["audio"]
assert len(column) == 1
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 73401)
@require_torchcodec
def test_resampling_at_loading_dataset_with_audio_feature_mp3(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.mp3")
data = {"audio": [audio_path]}
features = Features({"audio": Audio(sampling_rate=16000)})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 40124)
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 40124)
column = dset["audio"]
assert len(column) == 1
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 40124)
@require_torchcodec
def test_resampling_after_loading_dataset_with_audio_feature(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path]}
features = Features({"audio": Audio()})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 44100
dset = dset.cast_column("audio", Audio(sampling_rate=16000))
item = dset[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 73401)
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 73401)
column = dset["audio"]
assert len(column) == 1
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 73401)
@require_torchcodec
def test_resampling_after_loading_dataset_with_audio_feature_mp3(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.mp3")
data = {"audio": [audio_path]}
features = Features({"audio": Audio()})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 44100
dset = dset.cast_column("audio", Audio(sampling_rate=16000))
item = dset[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 40124)
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 40124)
column = dset["audio"]
assert len(column) == 1
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 16000
assert samples.data.shape == (2, 40124)
@require_torchcodec
@pytest.mark.parametrize(
"build_data",
[
lambda audio_path: {"audio": [audio_path]},
lambda audio_path: {"audio": [open(audio_path, "rb").read()]},
lambda audio_path: {"audio": [{"path": audio_path}]},
lambda audio_path: {"audio": [{"path": audio_path, "bytes": None}]},
lambda audio_path: {"audio": [{"path": audio_path, "bytes": open(audio_path, "rb").read()}]},
lambda audio_path: {"audio": [{"path": None, "bytes": open(audio_path, "rb").read()}]},
lambda audio_path: {"audio": [{"bytes": open(audio_path, "rb").read()}]},
],
)
def test_dataset_cast_to_audio_features(shared_datadir, build_data):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = build_data(audio_path)
dset = Dataset.from_dict(data)
item = dset.cast(Features({"audio": Audio()}))[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
item = dset.cast_column("audio", Audio())[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
@require_torchcodec
def test_dataset_concatenate_audio_features(shared_datadir):
# we use a different data structure between 1 and 2 to make sure they are compatible with each other
audio_path = str(shared_datadir / "test_audio_44100.wav")
data1 = {"audio": [audio_path]}
dset1 = Dataset.from_dict(data1, features=Features({"audio": Audio()}))
data2 = {"audio": [{"bytes": open(audio_path, "rb").read()}]}
dset2 = Dataset.from_dict(data2, features=Features({"audio": Audio()}))
concatenated_dataset = concatenate_datasets([dset1, dset2])
assert len(concatenated_dataset) == len(dset1) + len(dset2)
assert (
concatenated_dataset[0]["audio"].get_all_samples().data.shape == dset1[0]["audio"].get_all_samples().data.shape
)
assert (
concatenated_dataset[1]["audio"].get_all_samples().data.shape == dset2[0]["audio"].get_all_samples().data.shape
)
@require_torchcodec
def test_dataset_concatenate_nested_audio_features(shared_datadir):
# we use a different data structure between 1 and 2 to make sure they are compatible with each other
audio_path = str(shared_datadir / "test_audio_44100.wav")
features = Features({"list_of_structs_of_audios": [{"audio": Audio()}]})
data1 = {"list_of_structs_of_audios": [[{"audio": audio_path}]]}
dset1 = Dataset.from_dict(data1, features=features)
data2 = {"list_of_structs_of_audios": [[{"audio": {"bytes": open(audio_path, "rb").read()}}]]}
dset2 = Dataset.from_dict(data2, features=features)
concatenated_dataset = concatenate_datasets([dset1, dset2])
assert len(concatenated_dataset) == len(dset1) + len(dset2)
assert (
concatenated_dataset[0]["list_of_structs_of_audios"][0]["audio"].get_all_samples().data.shape
== dset1[0]["list_of_structs_of_audios"][0]["audio"].get_all_samples().data.shape
)
assert (
concatenated_dataset[1]["list_of_structs_of_audios"][0]["audio"].get_all_samples().data.shape
== dset2[0]["list_of_structs_of_audios"][0]["audio"].get_all_samples().data.shape
)
@require_torchcodec
def test_dataset_with_audio_feature_map_is_not_decoded(shared_datadir):
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path], "text": ["Hello"]}
features = Features({"audio": Audio(), "text": Value("string")})
dset = Dataset.from_dict(data, features=features)
expected_audio = features.encode_batch(data)["audio"][0]
for item in dset.cast_column("audio", Audio(decode=False)):
assert item.keys() == {"audio", "text"}
assert item == {"audio": expected_audio, "text": "Hello"}
def process_text(example):
example["text"] = example["text"] + " World!"
return example
processed_dset = dset.map(process_text)
for item in processed_dset.cast_column("audio", Audio(decode=False)):
assert item.keys() == {"audio", "text"}
assert item == {"audio": expected_audio, "text": "Hello World!"}
@require_torchcodec
def test_dataset_with_audio_feature_map_is_decoded(shared_datadir):
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path], "text": ["Hello"]}
features = Features({"audio": Audio(), "text": Value("string")})
dset = Dataset.from_dict(data, features=features)
def process_audio_sampling_rate_by_example(example):
sample_rate = example["audio"].get_all_samples().sample_rate
example["double_sampling_rate"] = 2 * sample_rate
return example
decoded_dset = dset.map(process_audio_sampling_rate_by_example)
for item in decoded_dset.cast_column("audio", Audio(decode=False)):
assert item.keys() == {"audio", "text", "double_sampling_rate"}
assert item["double_sampling_rate"] == 88200
def process_audio_sampling_rate_by_batch(batch):
double_sampling_rates = []
for audio in batch["audio"]:
double_sampling_rates.append(2 * audio.get_all_samples().sample_rate)
batch["double_sampling_rate"] = double_sampling_rates
return batch
decoded_dset = dset.map(process_audio_sampling_rate_by_batch, batched=True)
for item in decoded_dset.cast_column("audio", Audio(decode=False)):
assert item.keys() == {"audio", "text", "double_sampling_rate"}
assert item["double_sampling_rate"] == 88200
@require_torchcodec
def test_formatted_dataset_with_audio_feature(shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path, audio_path]}
features = Features({"audio": Audio()})
dset = Dataset.from_dict(data, features=features)
with dset.formatted_as("numpy"):
item = dset[0]
assert item.keys() == {"audio"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
column = dset["audio"]
assert len(column) == 2
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
with dset.formatted_as("pandas"):
item = dset[0]
assert item.shape == (1, 1)
assert item.columns == ["audio"]
assert isinstance(item["audio"][0], AudioDecoder)
samples = item["audio"][0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
batch = dset[:1]
assert batch.shape == (1, 1)
assert batch.columns == ["audio"]
assert isinstance(batch["audio"][0], AudioDecoder)
samples = batch["audio"][0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
column = dset["audio"]
assert len(column) == 2
assert isinstance(column[0], AudioDecoder)
samples = column[0].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
@pytest.fixture
def jsonl_audio_dataset_path(shared_datadir, tmp_path_factory):
import json
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = [{"audio": audio_path, "text": "Hello world!"}]
path = str(tmp_path_factory.mktemp("data") / "audio_dataset.jsonl")
with open(path, "w") as f:
for item in data:
f.write(json.dumps(item) + "\n")
return path
@require_torchcodec
@pytest.mark.parametrize("streaming", [False, True])
def test_load_dataset_with_audio_feature(streaming, jsonl_audio_dataset_path, shared_datadir):
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav")
data_files = jsonl_audio_dataset_path
features = Features({"audio": Audio(), "text": Value("string")})
dset = load_dataset("json", split="train", data_files=data_files, features=features, streaming=streaming)
item = dset[0] if not streaming else next(iter(dset))
assert item.keys() == {"audio", "text"}
assert isinstance(item["audio"], AudioDecoder)
samples = item["audio"].get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (2, 202311)
assert item["audio"].metadata.path == audio_path
@require_torchcodec
@pytest.mark.integration
def test_dataset_with_audio_feature_loaded_from_cache():
# load first time
ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean")
# load from cache
ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
assert isinstance(ds, Dataset)
@require_torchcodec
def test_dataset_with_audio_feature_undecoded(shared_datadir):
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path]}
features = Features({"audio": Audio(decode=False)})
dset = Dataset.from_dict(data, features=features)
item = dset[0]
assert item.keys() == {"audio"}
assert item["audio"] == {"path": audio_path, "bytes": None}
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert batch["audio"][0] == {"path": audio_path, "bytes": None}
column = dset["audio"]
assert len(column) == 1
assert column[0] == {"path": audio_path, "bytes": None}
@require_torchcodec
def test_formatted_dataset_with_audio_feature_undecoded(shared_datadir):
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path]}
features = Features({"audio": Audio(decode=False)})
dset = Dataset.from_dict(data, features=features)
with dset.formatted_as("numpy"):
item = dset[0]
assert item.keys() == {"audio"}
assert item["audio"] == {"path": audio_path, "bytes": None}
batch = dset[:1]
assert batch.keys() == {"audio"}
assert len(batch["audio"]) == 1
assert batch["audio"][0] == {"path": audio_path, "bytes": None}
column = dset["audio"]
assert len(column) == 1
assert column[0] == {"path": audio_path, "bytes": None}
with dset.formatted_as("pandas"):
item = dset[0]
assert item.shape == (1, 1)
assert item.columns == ["audio"]
assert item["audio"][0] == {"path": audio_path, "bytes": None}
batch = dset[:1]
assert batch.shape == (1, 1)
assert batch.columns == ["audio"]
assert batch["audio"][0] == {"path": audio_path, "bytes": None}
column = dset["audio"]
assert len(column) == 1
assert column[0] == {"path": audio_path, "bytes": None}
@require_torchcodec
def test_dataset_with_audio_feature_map_undecoded(shared_datadir):
audio_path = str(shared_datadir / "test_audio_44100.wav")
data = {"audio": [audio_path]}
features = Features({"audio": Audio(decode=False)})
dset = Dataset.from_dict(data, features=features)
def assert_audio_example_undecoded(example):
assert example["audio"] == {"path": audio_path, "bytes": None}
dset.map(assert_audio_example_undecoded)
def assert_audio_batch_undecoded(batch):
for audio in batch["audio"]:
assert audio == {"path": audio_path, "bytes": None}
dset.map(assert_audio_batch_undecoded, batched=True)
def test_audio_embed_storage(shared_datadir):
audio_path = str(shared_datadir / "test_audio_44100.wav")
example = {"bytes": None, "path": audio_path}
storage = pa.array([example], type=pa.struct({"bytes": pa.binary(), "path": pa.string()}))
embedded_storage = Audio().embed_storage(storage)
embedded_example = embedded_storage.to_pylist()[0]
assert embedded_example == {"bytes": open(audio_path, "rb").read(), "path": "test_audio_44100.wav"}
@require_torchcodec
def test_audio_decode_example_opus_convert_to_stereo(shared_datadir):
# GH 7837
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_48000.opus") # mono file
audio = Audio(num_channels=2)
decoded_example = audio.decode_example(audio.encode_example(audio_path))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == 48000
assert samples.data.shape == (2, 48000)
@require_torchcodec
def test_audio_decode_example_opus_convert_to_mono(shared_datadir):
# GH 7837
from torchcodec.decoders import AudioDecoder
audio_path = str(shared_datadir / "test_audio_44100.wav") # stereo file
audio = Audio(num_channels=1)
decoded_example = audio.decode_example(audio.encode_example(audio_path))
assert isinstance(decoded_example, AudioDecoder)
samples = decoded_example.get_all_samples()
assert samples.sample_rate == 44100
assert samples.data.shape == (1, 202311)