|
21 | 21 | from click.testing import CliRunner |
22 | 22 | from lhotse.index_pack import IndexPack, IndexPackCollectionSpec, index_pack_collection_key, write_index_pack |
23 | 23 | from lhotse.indexing import create_jsonl_index |
| 24 | +from omegaconf import OmegaConf |
24 | 25 | from scripts.dataloading import convert_indexes_to_idxpack as converter |
25 | 26 | from scripts.dataloading.convert_indexes_to_idxpack import main |
26 | 27 |
|
27 | 28 | from nemo.collections.common.data.lhotse import nemo_adapters, text_adapters |
| 29 | +from nemo.collections.common.data.lhotse.cutset import read_nemo_manifest |
28 | 30 | from nemo.collections.common.data.lhotse.indexed_adapters import create_tar_index as create_nemo_tar_index |
29 | 31 | from nemo.collections.common.data.lhotse.nemo_adapters import LazyNeMoIterator, LazyNeMoTarredIterator |
30 | 32 |
|
@@ -146,6 +148,117 @@ def test_convert_input_cfg_sidecars_to_one_index_pack(tmp_path): |
146 | 148 | assert pack.num_segments == 2 |
147 | 149 |
|
148 | 150 |
|
| 151 | +def test_flat_native_lists_use_aggregate_pack_and_preserve_positional_pairs(tmp_path, monkeypatch): |
| 152 | + manifests = [] |
| 153 | + declared_tar_paths = [] |
| 154 | + expected_texts = [] |
| 155 | + for position, (manifest_id, tar_id) in enumerate(((3076, 2), (4100, 0), (5200, 1))): |
| 156 | + manifest = tmp_path / f"manifest_{manifest_id}.jsonl" |
| 157 | + member = f"sample-{position}.wav" |
| 158 | + text = f"text-{position}" |
| 159 | + manifest.write_text( |
| 160 | + json.dumps( |
| 161 | + { |
| 162 | + "audio_filepath": member, |
| 163 | + "duration": 1.0, |
| 164 | + "text": text, |
| 165 | + "lang": "en", |
| 166 | + } |
| 167 | + ) |
| 168 | + + "\n" |
| 169 | + ) |
| 170 | + create_jsonl_index(manifest) |
| 171 | + manifests.append(str(manifest)) |
| 172 | + declared_tar_paths.append(f"ais://bucket/audio_{tar_id}.tar") |
| 173 | + expected_texts.append(text) |
| 174 | + |
| 175 | + input_cfg = tmp_path / "flat-lists.yaml" |
| 176 | + input_cfg.write_text( |
| 177 | + yaml.safe_dump( |
| 178 | + { |
| 179 | + "type": "nemo_tarred", |
| 180 | + "manifest_filepath": manifests, |
| 181 | + "tarred_audio_filepaths": declared_tar_paths, |
| 182 | + } |
| 183 | + ) |
| 184 | + ) |
| 185 | + output = tmp_path / "flat-lists.idxpack" |
| 186 | + result = CliRunner().invoke( |
| 187 | + main, |
| 188 | + [ |
| 189 | + "--output", |
| 190 | + str(output), |
| 191 | + "--native-tar-paths-only", |
| 192 | + str(input_cfg), |
| 193 | + ], |
| 194 | + ) |
| 195 | + assert result.exit_code == 0, result.output |
| 196 | + |
| 197 | + with IndexPack(output) as pack: |
| 198 | + manifest_collection = pack.collection(index_pack_collection_key("manifest", "jsonl", manifests)) |
| 199 | + tar_collection = pack.collection(index_pack_collection_key("tar", "nemo_tar", declared_tar_paths)) |
| 200 | + assert manifest_collection.sequence_count == 3 |
| 201 | + assert tar_collection.sequence_count == 3 |
| 202 | + assert [tar_collection.path_for_shard(idx) for idx in range(3)] == declared_tar_paths |
| 203 | + |
| 204 | + monkeypatch.setenv("USE_AIS_GET_BATCH", "true") |
| 205 | + config = OmegaConf.create( |
| 206 | + { |
| 207 | + "manifest_filepath": manifests, |
| 208 | + "tarred_audio_filepaths": declared_tar_paths, |
| 209 | + "indexed": True, |
| 210 | + "index_pack": str(output), |
| 211 | + "force_finite": True, |
| 212 | + } |
| 213 | + ) |
| 214 | + cuts, is_tarred = read_nemo_manifest(config) |
| 215 | + cuts = list(cuts) |
| 216 | + assert is_tarred |
| 217 | + assert [cut.supervisions[0].text for cut in cuts] == expected_texts |
| 218 | + assert [cut.recording.sources[0].source for cut in cuts] == [ |
| 219 | + f"{tar_path}/sample-{position}.wav" for position, tar_path in enumerate(declared_tar_paths) |
| 220 | + ] |
| 221 | + |
| 222 | + |
| 223 | +def test_converter_rejects_mixed_scalar_and_flat_native_pairs(tmp_path): |
| 224 | + input_cfg = tmp_path / "mixed-path-forms.yaml" |
| 225 | + input_cfg.write_text( |
| 226 | + yaml.safe_dump( |
| 227 | + { |
| 228 | + "type": "nemo_tarred", |
| 229 | + "manifest_filepath": [str(tmp_path / "manifest.jsonl")], |
| 230 | + "tarred_audio_filepaths": str(tmp_path / "audio.tar"), |
| 231 | + } |
| 232 | + ) |
| 233 | + ) |
| 234 | + |
| 235 | + result = CliRunner().invoke( |
| 236 | + main, |
| 237 | + ["--dry-run", "--output", str(tmp_path / "mixed.idxpack"), str(input_cfg)], |
| 238 | + ) |
| 239 | + assert result.exit_code != 0 |
| 240 | + assert "must both use scalar path specs or both use non-empty flat lists" in str(result.exception) |
| 241 | + |
| 242 | + |
| 243 | +def test_converter_rejects_nested_native_manifest_lists(tmp_path): |
| 244 | + input_cfg = tmp_path / "nested-lists.yaml" |
| 245 | + input_cfg.write_text( |
| 246 | + yaml.safe_dump( |
| 247 | + { |
| 248 | + "type": "nemo", |
| 249 | + "manifest_filepath": [[str(tmp_path / "manifest.jsonl"), 0.5]], |
| 250 | + } |
| 251 | + ) |
| 252 | + ) |
| 253 | + |
| 254 | + result = CliRunner().invoke( |
| 255 | + main, |
| 256 | + ["--dry-run", "--output", str(tmp_path / "nested.idxpack"), str(input_cfg)], |
| 257 | + ) |
| 258 | + assert result.exit_code != 0 |
| 259 | + assert "nested and weighted list forms are not supported" in str(result.exception) |
| 260 | + |
| 261 | + |
149 | 262 | def test_lazy_nemo_iterator_uses_pack_without_expanding_shards(tmp_path, monkeypatch): |
150 | 263 | manifests = [] |
151 | 264 | source_spec = str(tmp_path / "manifest__OP_0..1_CL_.jsonl") |
|
0 commit comments