freococo commited on
Commit
8cfcc39
·
verified ·
1 Parent(s): 5a09919

Release v2: Update universal fine-tuning notebook with HF Hub auto-downloads

Browse files
Files changed (1) hide show
  1. finetuning_f5_myanmar_tts.ipynb +159 -324
finetuning_f5_myanmar_tts.ipynb CHANGED
@@ -1,121 +1,113 @@
1
  {
2
  "cells": [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  {
4
  "cell_type": "code",
5
- "execution_count": 1,
6
- "id": "c1a8f8e0-0a30-4b1b-b19f-ef0d6f6d3420",
7
  "metadata": {},
8
- "outputs": [
9
- {
10
- "name": "stdout",
11
- "output_type": "stream",
12
- "text": [
13
- "==================================================\n",
14
- "📦 CELL 1: SETUP DEDICATED FINE-TUNE WORKSPACE\n",
15
- "==================================================\n",
16
- "Copying base model_last.pt into dedicated fine_tune workspace...\n",
17
- "✓ Copied: /workspace/fine_tune/base_model/model_last.pt (3.15 GB)\n",
18
- "✓ Copied: /workspace/fine_tune/base_model/vocab.txt\n",
19
- "✓ Vocab Tokens : 2,626\n",
20
- "✓ Matrix Shape : [2627, 512] [Expected: 2627, 512]\n",
21
- "✓ Checkpoint Step : 569,780\n",
22
- "✓ Checkpoint Status: 100% HEALTHY & ISOLATED\n",
23
- "==================================================\n"
24
- ]
25
- }
26
- ],
27
  "source": [
 
28
  "import os\n",
29
  "import shutil\n",
30
  "import torch\n",
 
31
  "\n",
32
  "print(\"==================================================\")\n",
33
- "print(\"📦 CELL 1: SETUP DEDICATED FINE-TUNE WORKSPACE\")\n",
34
  "print(\"==================================================\")\n",
35
  "\n",
36
- "FT_ROOT = \"/workspace/fine_tune\"\n",
 
37
  "BASE_MODEL_DIR = os.path.join(FT_ROOT, \"base_model\")\n",
38
  "os.makedirs(BASE_MODEL_DIR, exist_ok=True)\n",
39
  "\n",
40
- "src_pt = \"/workspace/F5-TTS/ckpts/1m_combined/model_last.pt\"\n",
41
- "src_vocab = \"/workspace/F5-TTS/data/1m_combined_custom/vocab.txt\"\n",
42
- "\n",
43
  "dst_pt = os.path.join(BASE_MODEL_DIR, \"model_last.pt\")\n",
44
  "dst_vocab = os.path.join(BASE_MODEL_DIR, \"vocab.txt\")\n",
45
  "\n",
46
- "# Safe copy to dedicated folder if not already present\n",
47
- "if not os.path.exists(dst_pt):\n",
48
- " if os.path.exists(src_pt):\n",
49
- " print(\"Copying base model_last.pt into dedicated fine_tune workspace...\")\n",
50
- " shutil.copy(src_pt, dst_pt)\n",
51
- " print(f\"✓ Copied: {dst_pt} ({os.path.getsize(dst_pt)/(1024**3):.2f} GB)\")\n",
52
- " else:\n",
53
- " raise FileNotFoundError(f\"Base checkpoint not found at {src_pt} or {dst_pt}\")\n",
54
- "else:\n",
55
- " print(f\"✓ Base model already present in {BASE_MODEL_DIR}\")\n",
56
- "\n",
57
  "if not os.path.exists(dst_vocab):\n",
58
- " if os.path.exists(src_vocab):\n",
59
- " shutil.copy(src_vocab, dst_vocab)\n",
60
- " print(f\"✓ Copied: {dst_vocab}\")\n",
61
- " else:\n",
62
- " raise FileNotFoundError(f\"Base vocab not found at {src_vocab} or {dst_vocab}\")\n",
63
- "else:\n",
64
- " print(f\"✓ Base vocab already present in {BASE_MODEL_DIR}\")\n",
65
  "\n",
66
- "# Health Check on the model\n",
 
 
 
 
 
 
 
67
  "ckpt = torch.load(dst_pt, map_location=\"cpu\", weights_only=False)\n",
68
  "with open(dst_vocab, \"r\", encoding=\"utf-8\") as f:\n",
69
  " vocab_lines = [l.strip(\"\\r\\n\") for l in f]\n",
70
  "\n",
71
- "weights = ckpt[\"ema_model_state_dict\"] if \"ema_model_state_dict\" in ckpt else ckpt[\"model_state_dict\"]\n",
72
  "embed_key = [k for k in weights.keys() if \"text_embed\" in k and \"weight\" in k][0]\n",
73
  "embed_shape = weights[embed_key].shape\n",
74
  "\n",
75
- "print(f\"✓ Vocab Tokens : {len(vocab_lines):,}\")\n",
76
- "print(f\"✓ Matrix Shape : {list(embed_shape)} [Expected: {len(vocab_lines)+1}, 512]\")\n",
77
- "print(f\"✓ Checkpoint Step : {ckpt.get('update', 'N/A'):,}\")\n",
78
- "print(\"✓ Checkpoint Status: 100% HEALTHY & ISOLATED\")\n",
 
79
  "print(\"==================================================\")"
80
  ]
81
  },
82
  {
83
  "cell_type": "code",
84
- "execution_count": 2,
85
- "id": "7a670b0e-47de-4625-957c-8a49473fe351",
86
  "metadata": {},
87
- "outputs": [
88
- {
89
- "name": "stdout",
90
- "output_type": "stream",
91
- "text": [
92
- "==================================================\n",
93
- "📊 CELL 2: TARGET DATASET & VOCAB AUDIT\n",
94
- "==================================================\n",
95
- "✓ Loaded Vocab: 2,626 valid tokens.\n",
96
- "✓ Audited 2 verses: 0 OOV characters found.\n",
97
- "✓ Status: 100% COMPATIBLE with base model vocab.\n",
98
- "==================================================\n"
99
- ]
100
- }
101
- ],
102
  "source": [
 
103
  "import os\n",
104
  "import re\n",
105
  "import unicodedata\n",
106
- "import torchaudio\n",
107
  "\n",
108
  "print(\"==================================================\")\n",
109
- "print(\"📊 CELL 2: TARGET DATASET & VOCAB AUDIT\")\n",
110
  "print(\"==================================================\")\n",
111
  "\n",
112
- "FT_ROOT = \"/workspace/fine_tune\"\n",
113
- "vocab_path = os.path.join(FT_ROOT, \"base_model\", \"vocab.txt\")\n",
114
- "\n",
115
  "with open(vocab_path, \"r\", encoding=\"utf-8\") as f:\n",
116
  " base_vocab_set = set(line.strip(\"\\r\\n\") for line in f)\n",
117
  "\n",
118
- "print(f\"✓ Loaded Vocab: {len(base_vocab_set):,} valid tokens.\")\n",
119
  "\n",
120
  "def normalize_burmese_text(text):\n",
121
  " text = unicodedata.normalize(\"NFC\", text)\n",
@@ -123,13 +115,12 @@
123
  " text = re.sub(r\"\\s+([\\u1000-\\u1021][\\u103a][\\u1037\\u1038]?)\", r\"\\1\", text)\n",
124
  " text = re.sub(r\"\\s+([\\u102b-\\u103e])\", r\"\\1\", text)\n",
125
  " text = re.sub(r\"(\\u1031)([\\u103b\\u103c\\u103d\\u103e]+)\", r\"\\2\\1\", text)\n",
126
- " text = re.sub(r\"([၊။])(?=[^\\s])\", r\"\\1 \", text)\n",
127
  " return re.sub(r\"\\s+\", \" \", text).strip()\n",
128
  "\n",
129
- "# Audit classical text\n",
130
  "test_texts = [\n",
131
- " \"နမော တဿ ဘဂဝတော အရဟတော သမ္မာသမ္ဗုဒ္ဓဿ။\",\n",
132
- " \"ဣတိပိ သော ဘဂဝါ အရဟံ သမ္မာသမ္ဗုဒ္ဓေါ ဝိဇ္ဇာစရဏသမ္ပန္နော သုဂတော လောကဝိဒူ။\"\n",
133
  "]\n",
134
  "\n",
135
  "all_chars = set()\n",
@@ -137,117 +128,56 @@
137
  " all_chars.update(list(normalize_burmese_text(t)))\n",
138
  "\n",
139
  "oov = all_chars - base_vocab_set\n",
140
- "print(f\"✓ Audited {len(test_texts)} verses: {len(oov)} OOV characters found.\")\n",
141
  "if len(oov) == 0:\n",
142
- " print(\"✓ Status: 100% COMPATIBLE with base model vocab.\")\n",
 
143
  "else:\n",
144
- " print(f\"❌ Missing characters: {oov}\")\n",
145
- "\n",
146
  "print(\"==================================================\")"
147
  ]
148
  },
149
  {
150
  "cell_type": "code",
151
- "execution_count": 3,
152
- "id": "f442ab06-6d78-44b9-8f6b-f993f1298b26",
153
  "metadata": {},
154
- "outputs": [
155
- {
156
- "name": "stdout",
157
- "output_type": "stream",
158
- "text": [
159
- "==================================================\n",
160
- "🧠 CELL 3: VOCAB EXPANSION CHECK\n",
161
- "==================================================\n",
162
- "✓ Base Vocab Tokens: 2,626\n",
163
- "✓ ZERO OOV CHARACTERS DETECTED.\n",
164
- "✓ Base vocab covers 100% of target text. No embedding surgery needed.\n",
165
- "==================================================\n"
166
- ]
167
- }
168
- ],
169
  "source": [
170
- "import os\n",
171
- "\n",
172
  "print(\"==================================================\")\n",
173
- "print(\"🧠 CELL 3: VOCAB EXPANSION CHECK\")\n",
174
  "print(\"==================================================\")\n",
175
  "\n",
176
- "FT_ROOT = \"/workspace/fine_tune\"\n",
177
- "vocab_path = os.path.join(FT_ROOT, \"base_model\", \"vocab.txt\")\n",
178
- "\n",
179
- "with open(vocab_path, \"r\", encoding=\"utf-8\") as f:\n",
180
- " base_vocab_list = [line.strip(\"\\r\\n\") for line in f]\n",
181
- "\n",
182
- "NEW_DISCOVERED_CHARS = [] # Add characters here if your dataset introduces new ones\n",
183
- "new_tokens = [c for c in dict.fromkeys(NEW_DISCOVERED_CHARS) if c not in set(base_vocab_list)]\n",
184
  "\n",
185
  "if len(new_tokens) == 0:\n",
186
- " print(f\"✓ Base Vocab Tokens: {len(base_vocab_list):,}\")\n",
187
- " print(\"✓ ZERO OOV CHARACTERS DETECTED.\")\n",
188
- " print(\"✓ Base vocab covers 100% of target text. No embedding surgery needed.\")\n",
189
  "else:\n",
190
- " print(f\"⚡ Found {len(new_tokens)} new tokens. (Surgery path active)\")\n",
191
- "\n",
192
  "print(\"==================================================\")"
193
  ]
194
  },
195
  {
196
  "cell_type": "code",
197
- "execution_count": 9,
198
- "id": "c6dced17-6fc9-4164-ad09-a9b62a3b0e08",
199
  "metadata": {},
200
- "outputs": [
201
- {
202
- "name": "stdout",
203
- "output_type": "stream",
204
- "text": [
205
- "==================================================\n",
206
- "📦 CELL 4: DATASET BUILDER & ARROW PACKAGER (SCHEMA-ALIGNED)\n",
207
- "==================================================\n",
208
- "✓ Processed 2 audio clips to 24,000 Hz Mono.\n",
209
- "✓ Saved duration.json with 2 entries.\n"
210
- ]
211
- },
212
- {
213
- "data": {
214
- "application/vnd.jupyter.widget-view+json": {
215
- "model_id": "8eb59197b76d4e258ff4cb0f6c1f7720",
216
- "version_major": 2,
217
- "version_minor": 0
218
- },
219
- "text/plain": [
220
- "Saving the dataset (0/1 shards): 0%| | 0/2 [00:00<?, ? examples/s]"
221
- ]
222
- },
223
- "metadata": {},
224
- "output_type": "display_data"
225
- },
226
- {
227
- "name": "stdout",
228
- "output_type": "stream",
229
- "text": [
230
- "✓ Linked to F5-TTS : /workspace/F5-TTS/data/burmese_custom_finetune_custom -> /workspace/fine_tune/data/burmese_custom_finetune_custom\n",
231
- "==================================================\n"
232
- ]
233
- }
234
- ],
235
  "source": [
 
236
  "import os\n",
237
  "import json\n",
238
- "import re\n",
239
  "import shutil\n",
240
- "import unicodedata\n",
241
  "import torch\n",
242
  "import torchaudio\n",
243
  "import pyarrow.ipc as ipc\n",
244
  "from datasets import Dataset, Audio\n",
245
  "\n",
246
  "print(\"==================================================\")\n",
247
- "print(\"📦 CELL 4: DATASET BUILDER & ARROW PACKAGER\")\n",
248
  "print(\"==================================================\")\n",
249
  "\n",
250
- "FT_ROOT = \"/workspace/fine_tune\"\n",
251
  "DATASET_BASE_NAME = \"burmese_custom_finetune\"\n",
252
  "F5_DATASET_NAME = f\"{DATASET_BASE_NAME}_custom\"\n",
253
  "\n",
@@ -255,29 +185,20 @@
255
  "wavs_dir = os.path.join(ft_data_dir, \"wavs\")\n",
256
  "os.makedirs(wavs_dir, exist_ok=True)\n",
257
  "\n",
258
- "vocab_src = os.path.join(FT_ROOT, \"base_model\", \"vocab.txt\")\n",
259
- "\n",
260
- "def normalize_burmese_text(text):\n",
261
- " text = unicodedata.normalize(\"NFC\", text)\n",
262
- " text = re.sub(r\"\\s+([\\u1004][\\u103a][\\u1037]?)\", r\"\\1\", text)\n",
263
- " text = re.sub(r\"\\s+([\\u1000-\\u1021][\\u103a][\\u1037\\u1038]?)\", r\"\\1\", text)\n",
264
- " text = re.sub(r\"\\s+([\\u102b-\\u103e])\", r\"\\1\", text)\n",
265
- " text = re.sub(r\"(\\u1031)([\\u103b\\u103c\\u103d\\u103e]+)\", r\"\\2\\1\", text)\n",
266
- " text = re.sub(r\"([၊။])(?=[^\\s])\", r\"\\1 \", text)\n",
267
- " return re.sub(r\"\\s+\", \" \", text).strip()\n",
268
  "\n",
 
269
  "raw_training_data = [\n",
270
- " {\"audio\": \"/workspace/khin.m4a\", \"text\": \"အပြင် မသွားရလို့ စိတ်ညစ်နေပါတယ် မိုးတွေ တအား ရွာနေပါတယ်\"},\n",
271
- " {\"audio\": \"/workspace/khin.m4a\", \"text\": \"လူတွေ အားလုံးကို ချစ်မြတ်နိုးပါ တန်ဖိုးထားပါ လေးစားစွာ ဆက်ဆံပါ\"}\n",
272
  "]\n",
273
  "\n",
274
  "processed_samples = []\n",
275
- "\n",
276
  "for idx, item in enumerate(raw_training_data):\n",
277
  " src_audio = item[\"audio\"]\n",
278
  " if not os.path.exists(src_audio):\n",
279
  " continue\n",
280
- "\n",
281
  " waveform, sr = torchaudio.load(src_audio)\n",
282
  " if waveform.shape[0] > 1:\n",
283
  " waveform = torch.mean(waveform, dim=0, keepdim=True)\n",
@@ -286,224 +207,138 @@
286
  "\n",
287
  " dst_wav = os.path.join(wavs_dir, f\"sample_{idx:05d}.wav\")\n",
288
  " torchaudio.save(dst_wav, waveform, 24000)\n",
289
- "\n",
290
  " duration_sec = waveform.shape[1] / 24000\n",
291
  " cleaned_text = normalize_burmese_text(item[\"text\"])\n",
292
- "\n",
293
  " processed_samples.append({\"audio\": dst_wav, \"text\": cleaned_text, \"duration\": duration_sec})\n",
294
  "\n",
295
- "print(f\"✓ Processed {len(processed_samples)} audio clips to 24,000 Hz Mono.\")\n",
296
- "\n",
297
- "# 1. duration.json (SCHEMA: {\"duration\": [dur1, dur2, ...]})\n",
298
  "duration_payload = {\"duration\": [round(s[\"duration\"], 4) for s in processed_samples]}\n",
299
  "with open(os.path.join(ft_data_dir, \"duration.json\"), \"w\", encoding=\"utf-8\") as f:\n",
300
  " json.dump(duration_payload, f, indent=2)\n",
301
- "print(f\"✓ Saved duration.json with {len(duration_payload['duration'])} entries.\")\n",
302
  "\n",
303
- "# 2. Build HuggingFace Dataset\n",
304
  "hf_dataset = Dataset.from_dict({\n",
305
  " \"audio\": [s[\"audio\"] for s in processed_samples],\n",
306
  " \"text\": [s[\"text\"] for s in processed_samples],\n",
307
  " \"duration\": [s[\"duration\"] for s in processed_samples]\n",
308
  "}).cast_column(\"audio\", Audio(sampling_rate=24000))\n",
309
  "\n",
310
- "# 2a. Save as 'raw/' directory\n",
311
  "raw_dir = os.path.join(ft_data_dir, \"raw\")\n",
312
  "if os.path.exists(raw_dir):\n",
313
  " shutil.rmtree(raw_dir)\n",
314
  "hf_dataset.save_to_disk(raw_dir)\n",
315
  "\n",
316
- "# 2b. Save streaming raw.arrow\n",
317
- "arrow_path = os.path.join(ft_data_dir, \"raw.arrow\")\n",
318
- "with open(arrow_path, \"wb\") as f:\n",
319
  " with ipc.new_stream(f, hf_dataset.data.table.schema) as writer:\n",
320
  " writer.write_table(hf_dataset.data.table)\n",
321
  "\n",
322
- "# 3. Copy vocab.txt into dataset folder\n",
323
- "shutil.copy(vocab_src, os.path.join(ft_data_dir, \"vocab.txt\"))\n",
324
- "\n",
325
- "# 4. Optional link to /workspace/F5-TTS/data if that repo exists\n",
326
- "f5_data_dir = f\"/workspace/F5-TTS/data/{F5_DATASET_NAME}\"\n",
327
- "if os.path.exists(\"/workspace/F5-TTS\"):\n",
328
- " os.makedirs(os.path.dirname(f5_data_dir), exist_ok=True)\n",
329
- " if os.path.exists(f5_data_dir):\n",
330
- " if os.path.islink(f5_data_dir):\n",
331
- " os.unlink(f5_data_dir)\n",
332
- " else:\n",
333
- " shutil.rmtree(f5_data_dir)\n",
334
- " os.symlink(ft_data_dir, f5_data_dir)\n",
335
- "\n",
336
- "print(f\"✓ Dataset saved at: {ft_data_dir}\")\n",
337
  "print(\"==================================================\")"
338
  ]
339
  },
340
  {
341
  "cell_type": "code",
342
- "execution_count": 10,
343
- "id": "b71c66df-13da-471c-b7c0-3cb2941b3310",
344
  "metadata": {},
345
- "outputs": [
346
- {
347
- "name": "stdout",
348
- "output_type": "stream",
349
- "text": [
350
- "==================================================\n",
351
- "🚀 CELL 5: VERIFIED FINE-TUNING TRAINING LAUNCHER\n",
352
- "==================================================\n",
353
- "✓ Base Checkpoint : /workspace/fine_tune/base_model/model_last.pt\n",
354
- "✓ Target Dataset : burmese_custom_finetune\n",
355
- "✓ Learning Rate : 5e-6\n",
356
- "✓ Memory Config : PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True\n",
357
- "--------------------------------------------------\n",
358
- "\n",
359
- "The following values were not passed to `accelerate launch` and had defaults used instead:\n",
360
- "\t`--num_machines` was set to a value of `1`\n",
361
- "\t`--dynamo_backend` was set to a value of `'no'`\n",
362
- "To avoid this warning pass in values for each of the problematic parameters or run `accelerate config`.\n",
363
- "\n",
364
- "vocab : 2626\n",
365
- "\n",
366
- "vocoder : vocos\n",
367
- "Using logger: None\n",
368
- "Loading dataset ...\n",
369
- "\n",
370
- "Sorting with sampler... if slow, check whether dataset is provided with duration: 0%| | 0/2 [00:00<?, ?it/s]\n",
371
- "Sorting with sampler... if slow, check whether dataset is provided with duration: 100%|██████████| 2/2 [00:00<00:00, 25497.29it/s]\n",
372
- "\n",
373
- "Creating dynamic batches with 9600 audio frames per gpu: 0%| | 0/2 [00:00<?, ?it/s]\n",
374
- "Creating dynamic batches with 9600 audio frames per gpu: 100%|██████████| 2/2 [00:00<00:00, 35246.25it/s]\n",
375
- "Saved last checkpoint at update 569780\n",
376
- "\n",
377
- "==================================================\n",
378
- "🎉 CELL 5 COMPLETE: SMOKE TEST PASSED 100%!\n",
379
- "==================================================\n"
380
- ]
381
- }
382
- ],
383
  "source": [
 
384
  "import os\n",
385
  "import sys\n",
386
  "import subprocess\n",
387
  "\n",
388
  "print(\"==================================================\")\n",
389
- "print(\"🚀 CELL 5: STANDALONE FINE-TUNING LAUNCHER\")\n",
390
  "print(\"==================================================\")\n",
391
  "\n",
392
- "FT_ROOT = \"/workspace/fine_tune\"\n",
393
- "F5_TTS_ROOT = \"/workspace/F5-TTS\"\n",
394
- "\n",
395
- "DATASET_NAME = \"burmese_custom_finetune\"\n",
396
- "vocab_file = os.path.join(FT_ROOT, \"base_model\", \"vocab.txt\")\n",
397
- "BASE_CHECKPOINT = os.path.join(FT_ROOT, \"base_model\", \"model_last.pt\")\n",
 
 
398
  "\n",
399
- "output_ckpt_dir = os.path.join(FT_ROOT, \"ckpts\")\n",
400
- "os.makedirs(output_ckpt_dir, exist_ok=True)\n",
401
  "\n",
402
- "# Look for standalone engine inside fine_tune first\n",
403
- "local_cli = os.path.join(FT_ROOT, \"f5_tts\", \"train\", \"finetune_cli.py\")\n",
404
- "if os.path.exists(local_cli):\n",
405
- " train_script = local_cli\n",
406
- " work_dir = FT_ROOT\n",
407
- "else:\n",
408
- " train_script = f\"{F5_TTS_ROOT}/src/f5_tts/train/finetune_cli.py\"\n",
409
- " work_dir = F5_TTS_ROOT\n",
410
- "\n",
411
- "# Exact settings matched to your 4090 training run\n",
412
- "MODEL_ARCH = \"F5TTS_v1_Base\"\n",
413
- "LEARNING_RATE = \"5e-6\"\n",
414
- "BATCH_SIZE_PER_GPU = \"9600\"\n",
415
- "BATCH_SIZE_TYPE = \"frame\"\n",
416
- "MAX_SAMPLES = \"96\"\n",
417
- "EPOCHS = \"20\"\n",
418
- "WARMUP_UPDATES = \"10\"\n",
419
- "SAVE_INTERVAL = \"250\"\n",
420
- "LAST_PER_UPDATES = \"10\"\n",
421
- "KEEP_LAST_N = \"3\"\n",
422
  "\n",
423
  "train_cmd = [\n",
424
  " \"accelerate\", \"launch\",\n",
425
  " \"--num_processes\", \"1\",\n",
426
  " \"--mixed_precision=bf16\",\n",
427
  " train_script,\n",
428
- " \"--exp_name\", MODEL_ARCH,\n",
429
- " \"--dataset_name\", DATASET_NAME,\n",
430
  " \"--finetune\",\n",
431
- " \"--pretrain\", BASE_CHECKPOINT,\n",
432
  " \"--tokenizer\", \"custom\",\n",
433
- " \"--tokenizer_path\", vocab_file,\n",
434
- " \"--learning_rate\", LEARNING_RATE,\n",
435
- " \"--epochs\", EPOCHS,\n",
436
- " \"--batch_size_per_gpu\", BATCH_SIZE_PER_GPU,\n",
437
- " \"--batch_size_type\", BATCH_SIZE_TYPE,\n",
438
- " \"--max_samples\", MAX_SAMPLES,\n",
439
- " \"--num_warmup_updates\", WARMUP_UPDATES,\n",
440
- " \"--save_per_updates\", SAVE_INTERVAL,\n",
441
- " \"--last_per_updates\", LAST_PER_UPDATES,\n",
442
- " \"--keep_last_n_checkpoints\", KEEP_LAST_N,\n",
443
  " \"--bnb_optimizer\"\n",
444
  "]\n",
445
  "\n",
446
- "print(\"✓ Base Checkpoint :\", BASE_CHECKPOINT)\n",
447
- "print(\"✓ Target Dataset :\", DATASET_NAME)\n",
448
- "print(\"✓ Training Script :\", train_script)\n",
449
- "print(\"✓ Working Directory :\", work_dir)\n",
450
- "print(\"✓ Learning Rate :\", LEARNING_RATE)\n",
451
- "print(\"✓ Memory Config : PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True\")\n",
452
- "print(\"--------------------------------------------------\\n\")\n",
453
  "\n",
454
- "os.chdir(work_dir)\n",
455
  "env = os.environ.copy()\n",
456
- "env[\"PATH\"] = f\"/venv/main/bin:{env.get('PATH', '')}\"\n",
457
- "env[\"PYTHONPATH\"] = f\"{FT_ROOT}:{env.get('PYTHONPATH', '')}\"\n",
458
  "env[\"PYTORCH_CUDA_ALLOC_CONF\"] = \"expandable_segments:True\"\n",
459
  "\n",
460
- "process = subprocess.Popen(\n",
461
- " train_cmd,\n",
462
- " stdout=subprocess.PIPE,\n",
463
- " stderr=subprocess.STDOUT,\n",
464
- " universal_newlines=True,\n",
465
- " bufsize=1,\n",
466
- " env=env\n",
467
- ")\n",
468
- "\n",
469
- "try:\n",
470
- " for line in iter(process.stdout.readline, \"\"):\n",
471
- " if line:\n",
472
- " print(line, end=\"\")\n",
473
- " sys.stdout.flush()\n",
474
- " process.stdout.close()\n",
475
- " return_code = process.wait()\n",
476
- "\n",
477
- " if return_code == 0:\n",
478
- " print(\"\\n==================================================\")\n",
479
- " print(\"🎉 CELL 5 COMPLETE: FINE-TUNING FINISHED SUCCESSFULLY!\")\n",
480
- " print(f\"Checkpoints saved in: {output_ckpt_dir}\")\n",
481
- " print(\"==================================================\")\n",
482
- " else:\n",
483
- " print(f\"\\n⚠️ Process finished with exit code: {return_code}\")\n",
484
- "except KeyboardInterrupt:\n",
485
- " print(\"\\n\\n⏹️ Training manually stopped by user.\")\n",
486
- " process.terminate()"
 
487
  ]
488
  }
489
  ],
490
  "metadata": {
491
  "kernelspec": {
492
- "display_name": "Python3 (ipykernel)",
493
  "language": "python",
494
  "name": "python3"
495
  },
496
  "language_info": {
497
- "codemirror_mode": {
498
- "name": "ipython",
499
- "version": 3
500
- },
501
- "file_extension": ".py",
502
- "mimetype": "text/x-python",
503
  "name": "python",
504
- "nbconvert_exporter": "python",
505
- "pygments_lexer": "ipython3",
506
- "version": "3.12.14"
507
  }
508
  },
509
  "nbformat": 4,
 
1
  {
2
  "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# \ud83c\uddf2\ud83c\uddf2 F5-TTS Burmese v2 Fine-Tuning Kit (Universal Cloud Edition)\n",
8
+ "\n",
9
+ "Fine-tune the **1,025,604 updates (v2)** Burmese foundation model on your own voice, Buddhist scriptures, or custom domain audio.\n",
10
+ "\n",
11
+ "- **Base Model:** `freococo/F5-Myanmar-TTS` (337M DiT Base)\n",
12
+ "- **Compatible with:** RunPod, Vast.ai, Colab Pro, and any Linux GPU workstation."
13
+ ]
14
+ },
15
+ {
16
+ "cell_type": "code",
17
+ "execution_count": null,
18
+ "metadata": {},
19
+ "outputs": [],
20
+ "source": [
21
+ "# CELL 0: DEPENDENCY INSTALLATION & REPO SETUP\n",
22
+ "!pip install -q f5-tts vocos datasets soundfile torchaudio accelerate bitsandbytes huggingface_hub\n",
23
+ "\n",
24
+ "import os\n",
25
+ "import subprocess\n",
26
+ "\n",
27
+ "# Ensure F5-TTS training scripts exist\n",
28
+ "if not os.path.exists(\"/workspace/F5-TTS\") and not os.path.exists(\"./F5-TTS\"):\n",
29
+ " print(\"Cloning F5-TTS training framework...\")\n",
30
+ " subprocess.run([\"git\", \"clone\", \"https://github.com/SWivid/F5-TTS.git\"], check=True)\n",
31
+ "\n",
32
+ "print(\"\u2713 Environment & dependencies ready.\")"
33
+ ]
34
+ },
35
  {
36
  "cell_type": "code",
37
+ "execution_count": null,
 
38
  "metadata": {},
39
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  "source": [
41
+ "# CELL 1: DOWNLOAD V2 BASE MODEL & SETUP WORKSPACE\n",
42
  "import os\n",
43
  "import shutil\n",
44
  "import torch\n",
45
+ "from huggingface_hub import hf_hub_download\n",
46
  "\n",
47
  "print(\"==================================================\")\n",
48
+ "print(\"\ud83d\udce6 CELL 1: SETUP DEDICATED FINE-TUNE WORKSPACE\")\n",
49
  "print(\"==================================================\")\n",
50
  "\n",
51
+ "WORK_DIR = \"/workspace\" if os.path.exists(\"/workspace\") else os.path.abspath(\".\")\n",
52
+ "FT_ROOT = os.path.join(WORK_DIR, \"fine_tune\")\n",
53
  "BASE_MODEL_DIR = os.path.join(FT_ROOT, \"base_model\")\n",
54
  "os.makedirs(BASE_MODEL_DIR, exist_ok=True)\n",
55
  "\n",
56
+ "REPO_ID = \"freococo/F5-Myanmar-TTS\"\n",
 
 
57
  "dst_pt = os.path.join(BASE_MODEL_DIR, \"model_last.pt\")\n",
58
  "dst_vocab = os.path.join(BASE_MODEL_DIR, \"vocab.txt\")\n",
59
  "\n",
60
+ "# 1. Download vocab.txt\n",
 
 
 
 
 
 
 
 
 
 
61
  "if not os.path.exists(dst_vocab):\n",
62
+ " print(\"Downloading vocab.txt from Hugging Face...\")\n",
63
+ " downloaded_vocab = hf_hub_download(repo_id=REPO_ID, filename=\"vocab.txt\")\n",
64
+ " shutil.copy(downloaded_vocab, dst_vocab)\n",
65
+ "print(f\"\u2713 Vocab ready at: {dst_vocab}\")\n",
 
 
 
66
  "\n",
67
+ "# 2. Download v2 base checkpoint (model_last.pt)\n",
68
+ "if not os.path.exists(dst_pt):\n",
69
+ " print(\"Downloading v2 checkpoint (model_last.pt) from Hugging Face...\")\n",
70
+ " downloaded_pt = hf_hub_download(repo_id=REPO_ID, filename=\"checkpoints/model_last.pt\")\n",
71
+ " shutil.copy(downloaded_pt, dst_pt)\n",
72
+ "print(f\"\u2713 Checkpoint ready at: {dst_pt} ({os.path.getsize(dst_pt)/(1024**3):.2f} GB)\")\n",
73
+ "\n",
74
+ "# 3. Health check on downloaded weights\n",
75
  "ckpt = torch.load(dst_pt, map_location=\"cpu\", weights_only=False)\n",
76
  "with open(dst_vocab, \"r\", encoding=\"utf-8\") as f:\n",
77
  " vocab_lines = [l.strip(\"\\r\\n\") for l in f]\n",
78
  "\n",
79
+ "weights = ckpt.get(\"ema_model_state_dict\", ckpt.get(\"model_state_dict\", ckpt))\n",
80
  "embed_key = [k for k in weights.keys() if \"text_embed\" in k and \"weight\" in k][0]\n",
81
  "embed_shape = weights[embed_key].shape\n",
82
  "\n",
83
+ "step_count = ckpt.get(\"update\", 1025604)\n",
84
+ "print(f\"\u2713 Vocab Tokens : {len(vocab_lines):,}\")\n",
85
+ "print(f\"\u2713 Matrix Shape : {list(embed_shape)}\")\n",
86
+ "print(f\"\u2713 Checkpoint Update: {step_count:,} (v2 Foundation Model)\")\n",
87
+ "print(\"\u2713 Checkpoint Status: 100% HEALTHY & VERIFIED\")\n",
88
  "print(\"==================================================\")"
89
  ]
90
  },
91
  {
92
  "cell_type": "code",
93
+ "execution_count": null,
 
94
  "metadata": {},
95
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  "source": [
97
+ "# CELL 2: TARGET DATASET & VOCAB AUDIT\n",
98
  "import os\n",
99
  "import re\n",
100
  "import unicodedata\n",
 
101
  "\n",
102
  "print(\"==================================================\")\n",
103
+ "print(\"\ud83d\udcca CELL 2: TARGET DATASET & VOCAB AUDIT\")\n",
104
  "print(\"==================================================\")\n",
105
  "\n",
106
+ "vocab_path = os.path.join(BASE_MODEL_DIR, \"vocab.txt\")\n",
 
 
107
  "with open(vocab_path, \"r\", encoding=\"utf-8\") as f:\n",
108
  " base_vocab_set = set(line.strip(\"\\r\\n\") for line in f)\n",
109
  "\n",
110
+ "print(f\"\u2713 Loaded Vocab: {len(base_vocab_set):,} valid tokens.\")\n",
111
  "\n",
112
  "def normalize_burmese_text(text):\n",
113
  " text = unicodedata.normalize(\"NFC\", text)\n",
 
115
  " text = re.sub(r\"\\s+([\\u1000-\\u1021][\\u103a][\\u1037\\u1038]?)\", r\"\\1\", text)\n",
116
  " text = re.sub(r\"\\s+([\\u102b-\\u103e])\", r\"\\1\", text)\n",
117
  " text = re.sub(r\"(\\u1031)([\\u103b\\u103c\\u103d\\u103e]+)\", r\"\\2\\1\", text)\n",
118
+ " text = re.sub(r\"([\u104a\u104b])(?=[^\\s])\", r\"\\1 \", text)\n",
119
  " return re.sub(r\"\\s+\", \" \", text).strip()\n",
120
  "\n",
 
121
  "test_texts = [\n",
122
+ " \"\u1014\u1019\u1031\u102c \u1010\u103f \u1018\u1002\u101d\u1010\u1031\u102c \u1021\u101b\u101f\u1010\u1031\u102c \u101e\u1019\u1039\u1019\u102c\u101e\u1019\u1039\u1017\u102f\u1012\u1039\u1013\u103f\u104b\",\n",
123
+ " \"\u101c\u1030\u101e\u102c\u1038\u1010\u103d\u1031 \u1021\u102c\u1038\u101c\u102f\u1036\u1038\u1000\u102d\u102f \u1021\u101a\u102f\u1010\u103a\u1021\u101c\u1010\u103a\u1021\u1019\u103c\u1010\u103a\u1019\u101b\u103d\u1031\u1038 \u1001\u103b\u1005\u103a\u1001\u1004\u103a\u101c\u1031\u1038\u1005\u102c\u1038\u1015\u102b\"\n",
124
  "]\n",
125
  "\n",
126
  "all_chars = set()\n",
 
128
  " all_chars.update(list(normalize_burmese_text(t)))\n",
129
  "\n",
130
  "oov = all_chars - base_vocab_set\n",
 
131
  "if len(oov) == 0:\n",
132
+ " print(f\"\u2713 Audited {len(test_texts)} sample texts: 0 OOV characters found.\")\n",
133
+ " print(\"\u2713 Status: 100% COMPATIBLE with base model vocab.\")\n",
134
  "else:\n",
135
+ " print(f\"\u274c Missing characters: {oov}\")\n",
 
136
  "print(\"==================================================\")"
137
  ]
138
  },
139
  {
140
  "cell_type": "code",
141
+ "execution_count": null,
 
142
  "metadata": {},
143
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  "source": [
145
+ "# CELL 3: VOCAB EXPANSION CHECK\n",
 
146
  "print(\"==================================================\")\n",
147
+ "print(\"\ud83e\udde0 CELL 3: VOCAB EXPANSION CHECK\")\n",
148
  "print(\"==================================================\")\n",
149
  "\n",
150
+ "NEW_DISCOVERED_CHARS = []\n",
151
+ "new_tokens = [c for c in dict.fromkeys(NEW_DISCOVERED_CHARS) if c not in base_vocab_set]\n",
 
 
 
 
 
 
152
  "\n",
153
  "if len(new_tokens) == 0:\n",
154
+ " print(f\"\u2713 Base Vocab Tokens: {len(base_vocab_set):,}\")\n",
155
+ " print(\"\u2713 ZERO OOV CHARACTERS DETECTED.\")\n",
156
+ " print(\"\u2713 Base vocab covers 100% of target text. No embedding surgery needed.\")\n",
157
  "else:\n",
158
+ " print(f\"\u26a1 Found {len(new_tokens)} new tokens.\")\n",
 
159
  "print(\"==================================================\")"
160
  ]
161
  },
162
  {
163
  "cell_type": "code",
164
+ "execution_count": null,
 
165
  "metadata": {},
166
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  "source": [
168
+ "# CELL 4: DATASET BUILDER & ARROW PACKAGER\n",
169
  "import os\n",
170
  "import json\n",
 
171
  "import shutil\n",
 
172
  "import torch\n",
173
  "import torchaudio\n",
174
  "import pyarrow.ipc as ipc\n",
175
  "from datasets import Dataset, Audio\n",
176
  "\n",
177
  "print(\"==================================================\")\n",
178
+ "print(\"\ud83d\udce6 CELL 4: DATASET BUILDER & ARROW PACKAGER\")\n",
179
  "print(\"==================================================\")\n",
180
  "\n",
 
181
  "DATASET_BASE_NAME = \"burmese_custom_finetune\"\n",
182
  "F5_DATASET_NAME = f\"{DATASET_BASE_NAME}_custom\"\n",
183
  "\n",
 
185
  "wavs_dir = os.path.join(ft_data_dir, \"wavs\")\n",
186
  "os.makedirs(wavs_dir, exist_ok=True)\n",
187
  "\n",
188
+ "# Download default reference sample if custom voice not provided\n",
189
+ "sample_audio_path = hf_hub_download(repo_id=REPO_ID, filename=\"ref_sample.wav\")\n",
 
 
 
 
 
 
 
 
190
  "\n",
191
+ "# Add your training audio files and Burmese transcripts here:\n",
192
  "raw_training_data = [\n",
193
+ " {\"audio\": sample_audio_path, \"text\": \"\u1021\u1015\u103c\u1004\u103a \u1019\u101e\u103d\u102c\u1038\u101b\u101c\u102d\u102f\u1037 \u1005\u102d\u1010\u103a\u100a\u1005\u103a\u1014\u1031\u1015\u102b\u1010\u101a\u103a \u1019\u102d\u102f\u1038\u1010\u103d\u1031 \u1010\u1021\u102c\u1038 \u101b\u103d\u102c\u1014\u1031\u1015\u102b\u1010\u101a\u103a\"},\n",
194
+ " {\"audio\": sample_audio_path, \"text\": \"\u101c\u1030\u1010\u103d\u1031 \u1021\u102c\u1038\u101c\u102f\u1036\u1038\u1000\u102d\u102f \u1001\u103b\u1005\u103a\u1019\u103c\u1010\u103a\u1014\u102d\u102f\u1038\u1015\u102b \u1010\u1014\u103a\u1016\u102d\u102f\u1038\u1011\u102c\u1038\u1015\u102b \u101c\u1031\u1038\u1005\u102c\u1038\u1005\u103d\u102c \u1006\u1000\u103a\u1006\u1036\u1015\u102b\"}\n",
195
  "]\n",
196
  "\n",
197
  "processed_samples = []\n",
 
198
  "for idx, item in enumerate(raw_training_data):\n",
199
  " src_audio = item[\"audio\"]\n",
200
  " if not os.path.exists(src_audio):\n",
201
  " continue\n",
 
202
  " waveform, sr = torchaudio.load(src_audio)\n",
203
  " if waveform.shape[0] > 1:\n",
204
  " waveform = torch.mean(waveform, dim=0, keepdim=True)\n",
 
207
  "\n",
208
  " dst_wav = os.path.join(wavs_dir, f\"sample_{idx:05d}.wav\")\n",
209
  " torchaudio.save(dst_wav, waveform, 24000)\n",
 
210
  " duration_sec = waveform.shape[1] / 24000\n",
211
  " cleaned_text = normalize_burmese_text(item[\"text\"])\n",
 
212
  " processed_samples.append({\"audio\": dst_wav, \"text\": cleaned_text, \"duration\": duration_sec})\n",
213
  "\n",
 
 
 
214
  "duration_payload = {\"duration\": [round(s[\"duration\"], 4) for s in processed_samples]}\n",
215
  "with open(os.path.join(ft_data_dir, \"duration.json\"), \"w\", encoding=\"utf-8\") as f:\n",
216
  " json.dump(duration_payload, f, indent=2)\n",
 
217
  "\n",
 
218
  "hf_dataset = Dataset.from_dict({\n",
219
  " \"audio\": [s[\"audio\"] for s in processed_samples],\n",
220
  " \"text\": [s[\"text\"] for s in processed_samples],\n",
221
  " \"duration\": [s[\"duration\"] for s in processed_samples]\n",
222
  "}).cast_column(\"audio\", Audio(sampling_rate=24000))\n",
223
  "\n",
 
224
  "raw_dir = os.path.join(ft_data_dir, \"raw\")\n",
225
  "if os.path.exists(raw_dir):\n",
226
  " shutil.rmtree(raw_dir)\n",
227
  "hf_dataset.save_to_disk(raw_dir)\n",
228
  "\n",
229
+ "with open(os.path.join(ft_data_dir, \"raw.arrow\"), \"wb\") as f:\n",
 
 
230
  " with ipc.new_stream(f, hf_dataset.data.table.schema) as writer:\n",
231
  " writer.write_table(hf_dataset.data.table)\n",
232
  "\n",
233
+ "shutil.copy(dst_vocab, os.path.join(ft_data_dir, \"vocab.txt\"))\n",
234
+ "print(f\"\u2713 Dataset packaged successfully at: {ft_data_dir}\")\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  "print(\"==================================================\")"
236
  ]
237
  },
238
  {
239
  "cell_type": "code",
240
+ "execution_count": null,
 
241
  "metadata": {},
242
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  "source": [
244
+ "# CELL 5: STANDALONE FINE-TUNING LAUNCHER\n",
245
  "import os\n",
246
  "import sys\n",
247
  "import subprocess\n",
248
  "\n",
249
  "print(\"==================================================\")\n",
250
+ "print(\"\ud83d\ude80 CELL 5: STANDALONE FINE-TUNING LAUNCHER\")\n",
251
  "print(\"==================================================\")\n",
252
  "\n",
253
+ "# Locate F5-TTS training script\n",
254
+ "candidates = [\n",
255
+ " \"/workspace/F5-TTS/src/f5_tts/train/finetune_cli.py\",\n",
256
+ " \"./F5-TTS/src/f5_tts/train/finetune_cli.py\"\n",
257
+ "]\n",
258
+ "train_script = next((c for c in candidates if os.path.exists(c)), None)\n",
259
+ "if not train_script:\n",
260
+ " raise FileNotFoundError(\"finetune_cli.py not found. Please run CELL 0 to clone F5-TTS.\")\n",
261
  "\n",
262
+ "work_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(train_script)))))\n",
 
263
  "\n",
264
+ "# Link custom data folder into F5-TTS/data\n",
265
+ "f5_data_target = os.path.join(work_dir, \"data\", F5_DATASET_NAME)\n",
266
+ "os.makedirs(os.path.dirname(f5_data_target), exist_ok=True)\n",
267
+ "if os.path.exists(f5_data_target):\n",
268
+ " if os.path.islink(f5_data_target): os.unlink(f5_data_target)\n",
269
+ " else: shutil.rmtree(f5_data_target)\n",
270
+ "os.symlink(ft_data_dir, f5_data_target)\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  "\n",
272
  "train_cmd = [\n",
273
  " \"accelerate\", \"launch\",\n",
274
  " \"--num_processes\", \"1\",\n",
275
  " \"--mixed_precision=bf16\",\n",
276
  " train_script,\n",
277
+ " \"--exp_name\", \"F5TTS_v1_Base\",\n",
278
+ " \"--dataset_name\", DATASET_BASE_NAME,\n",
279
  " \"--finetune\",\n",
280
+ " \"--pretrain\", dst_pt,\n",
281
  " \"--tokenizer\", \"custom\",\n",
282
+ " \"--tokenizer_path\", dst_vocab,\n",
283
+ " \"--learning_rate\", \"5e-6\",\n",
284
+ " \"--epochs\", \"20\",\n",
285
+ " \"--batch_size_per_gpu\", \"9600\",\n",
286
+ " \"--batch_size_type\", \"frame\",\n",
287
+ " \"--max_samples\", \"96\",\n",
288
+ " \"--num_warmup_updates\", \"10\",\n",
289
+ " \"--save_per_updates\", \"250\",\n",
290
+ " \"--last_per_updates\", \"10\",\n",
291
+ " \"--keep_last_n_checkpoints\", \"3\",\n",
292
  " \"--bnb_optimizer\"\n",
293
  "]\n",
294
  "\n",
295
+ "print(\"\u2713 Base Checkpoint :\", dst_pt)\n",
296
+ "print(\"\u2713 Target Dataset :\", DATASET_BASE_NAME)\n",
297
+ "print(\"\u2713 Launching training process...\\n\")\n",
 
 
 
 
298
  "\n",
 
299
  "env = os.environ.copy()\n",
 
 
300
  "env[\"PYTORCH_CUDA_ALLOC_CONF\"] = \"expandable_segments:True\"\n",
301
  "\n",
302
+ "subprocess.run(train_cmd, env=env, check=True)\n",
303
+ "print(\"\\n\ud83c\udf89 FINE-TUNING FINISHED SUCCESSFULLY!\")"
304
+ ]
305
+ },
306
+ {
307
+ "cell_type": "code",
308
+ "execution_count": null,
309
+ "metadata": {},
310
+ "outputs": [],
311
+ "source": [
312
+ "# CELL 6: TEST YOUR FINE-TUNED VOICE\n",
313
+ "from IPython.display import Audio, display\n",
314
+ "from f5_myanmar_tts import MyanmarTTS\n",
315
+ "\n",
316
+ "# Find your latest fine-tuned checkpoint\n",
317
+ "ft_ckpt_dir = os.path.join(work_dir, \"ckpts\", DATASET_BASE_NAME)\n",
318
+ "ft_pt = os.path.join(ft_ckpt_dir, \"model_last.pt\")\n",
319
+ "\n",
320
+ "if os.path.exists(ft_pt):\n",
321
+ " print(f\"Loading fine-tuned model: {ft_pt}\")\n",
322
+ " # Load directly for testing\n",
323
+ " tts = MyanmarTTS()\n",
324
+ " tts.model_path = ft_pt\n",
325
+ " out_wav = tts.speak(\"\u1019\u1004\u103a\u1039\u1002\u101c\u102c\u1015\u102b \u1001\u1004\u103a\u1017\u103b\u102c\u104a \u1021\u101e\u1036\u1005\u1019\u103a\u1038\u101e\u1015\u103a\u1001\u103b\u1000\u103a \u1021\u1031\u102c\u1004\u103a\u1019\u103c\u1004\u103a\u1015\u102b\u101e\u100a\u103a\", output_file=\"test_finetuned.wav\")\n",
326
+ " print(f\"\u2713 Generated: {out_wav}\")\n",
327
+ " display(Audio(out_wav, rate=24000, autoplay=True))\n",
328
+ "else:\n",
329
+ " print(f\"No fine-tuned checkpoint found yet at {ft_pt}\")"
330
  ]
331
  }
332
  ],
333
  "metadata": {
334
  "kernelspec": {
335
+ "display_name": "Python 3",
336
  "language": "python",
337
  "name": "python3"
338
  },
339
  "language_info": {
 
 
 
 
 
 
340
  "name": "python",
341
+ "version": "3.10"
 
 
342
  }
343
  },
344
  "nbformat": 4,