{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "source": [ "#convert file audio to mp3 32k" ], "metadata": { "id": "XE8k_JyY5eBb" } }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Wyv972sc5Lb4" }, "outputs": [], "source": [ "import os\n", "from multiprocessing import Pool, cpu_count\n", "from tqdm import tqdm\n", "import subprocess\n", "\n", "def process_file_ffmpeg(args):\n", " file_path, input_folder, output_folder = args\n", " rel_path = os.path.relpath(file_path, input_folder)\n", " rel_path = os.path.splitext(rel_path)[0] + \".mp3\" # luôn xuất mp3\n", " out_path = os.path.join(output_folder, rel_path)\n", " os.makedirs(os.path.dirname(out_path), exist_ok=True)\n", "\n", " cmd = [\n", " \"ffmpeg\",\n", " \"-y\", # overwrite nếu đã tồn tại\n", " \"-i\", file_path,\n", " \"-ar\", \"32000\", # sample rate 32kHz\n", " \"-ac\", \"1\", # stereo set thành 2 còn mono set thành 1\n", " \"-b:a\", \"192k\", # bitrate\n", " out_path\n", " ]\n", "\n", " try:\n", " subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)\n", " return True\n", " except subprocess.CalledProcessError:\n", " print(f\"❌ Lỗi khi xử lý {file_path}\")\n", " return False\n", "\n", "def convert_audio_ffmpeg_multiprocessing(input_folder, output_folder, num_workers=None):\n", " audio_exts = ('.mp3', '.wav', '.flac', '.m4a', '.ogg')\n", "\n", " # Lấy danh sách tất cả file audio\n", " all_files = []\n", " for root, _, files in os.walk(input_folder):\n", " for f in files:\n", " if f.lower().endswith(audio_exts):\n", " all_files.append(os.path.join(root, f))\n", "\n", " if num_workers is None:\n", " num_workers = cpu_count()\n", "\n", " args_list = [(f, input_folder, output_folder) for f in all_files]\n", "\n", " # Multiprocessing + tqdm\n", " with Pool(num_workers) as pool:\n", " for _ in tqdm(pool.imap_unordered(process_file_ffmpeg, args_list),\n", " total=len(args_list), desc=\"Converting to 32kHz MP3\"):\n", " pass\n", "\n", "# --- Ví dụ sử dụng ---\n", "input_dir = \"/content/dataset\"\n", "output_dir = \"/content/dataset_process\"\n", "convert_audio_ffmpeg_multiprocessing(input_dir, output_dir)\n" ] }, { "cell_type": "markdown", "source": [ "#mp3 to hdf5" ], "metadata": { "id": "kIoHloKr5ky7" } }, { "cell_type": "markdown", "source": [ "##Audioset" ], "metadata": { "id": "pctubCgR5sli" } }, { "cell_type": "code", "source": [ "import h5py\n", "import pandas as pd\n", "import numpy as np\n", "import csv\n", "import os\n", "import io\n", "import av\n", "\n", "def decode_mp3(mp3_arr):\n", " \"\"\"\n", " Giải mã một mảng uint8 đại diện cho một file MP3.\n", " :rtype: np.array\n", " \"\"\"\n", " container = av.open(io.BytesIO(mp3_arr.tobytes())) # Đọc dữ liệu MP3\n", " stream = next(s for s in container.streams if s.type == 'audio') # Lấy stream âm thanh\n", " a = []\n", " for i, packet in enumerate(container.demux(stream)): # Demux các gói dữ liệu âm thanh\n", " for frame in packet.decode(): # Giải mã frame\n", " a.append(frame.to_ndarray().reshape(-1)) # Chuyển đổi frame thành mảng numpy\n", " waveform = np.concatenate(a) # Kết nối tất cả các frame lại\n", " if waveform.dtype != 'float32': # Kiểm tra loại dữ liệu\n", " raise RuntimeError(\"Unexpected wave type\")\n", " return waveform\n", "\n", "# %%\n", "base_dir = \"/content/output_\"\n", "balanced_csv= '/content/new_updated_balanced_train_segments.csv'\n", "eval_csv= '/content/new_eval_segments.csv'\n", "mp3_path = \"/content/dataset/\"\n", "\n", "\n", "# %%\n", "\n", "\n", "def read_metadata(csv_path, classes_num, id_to_ix):\n", " \"\"\"Read metadata of AudioSet from a csv file.\"\"\"\n", "\n", " audio_names = []\n", " targets = []\n", "\n", " with open(csv_path, 'r') as fr:\n", " reader = csv.reader(fr)\n", " next(reader) # Skip header line if exists\n", " next(reader) # Skip another potential header line\n", " next(reader) # Skip another potential header line\n", "\n", " for line in reader:\n", " if len(line) < 4:\n", " continue # Skip malformed lines\n", "\n", " audio_name = 'Y{}.mp3'.format(line[0]) # Assumed naming convention\n", " label_ids = line[3].strip('\"').split(',')\n", "\n", " audio_names.append(audio_name)\n", " target = np.zeros(classes_num, dtype=bool)\n", "\n", " for label_id in label_ids:\n", " if label_id in id_to_ix:\n", " ix = id_to_ix[label_id]\n", " target[ix] = 1\n", " else:\n", " print(f\"Warning: Label ID {label_id} not found in id_to_ix.\")\n", "\n", " targets.append(target)\n", "\n", " meta_dict = {'audio_name': np.array(audio_names), 'target': np.array(targets)}\n", " print(meta_dict)\n", " return meta_dict\n", "\n", "# Load label\n", "with open('/content/new_class_labels_indices_filter_discard.csv', 'r') as f:\n", " reader = csv.reader(f, delimiter=',')\n", " lines = list(reader)\n", "\n", "labels = []\n", "ids = [] # Each label has a unique id such as \"/m/068hy\"\n", "for i1 in range(1, len(lines)):\n", " id = lines[i1][1]\n", " label = lines[i1][2]\n", " ids.append(id)\n", " labels.append(label)\n", "\n", "classes_num = len(labels)\n", "\n", "lb_to_ix = {label : i for i, label in enumerate(labels)}\n", "ix_to_lb = {i : label for i, label in enumerate(labels)}\n", "\n", "id_to_ix = {id : i for i, id in enumerate(ids)}\n", "ix_to_id = {i : id for i, id in enumerate(ids)}\n", "\n", "# %%\n", "\n", "def check_available(balanced_csv,balanced_audio_path,prefix=None):\n", " meta_csv = read_metadata(balanced_csv,classes_num,id_to_ix)\n", " #print(meta_csv)\n", " audios_num = len(meta_csv['audio_name'])\n", " found=0\n", " notfound=0\n", " available_files=[]\n", " available_targets=[]\n", " if prefix is None:\n", " prefix = os.path.basename(balanced_csv)[:-4]\n", " for n in range(audios_num):\n", " audio_path = meta_csv['audio_name'][n]\n", " #print(balanced_audio_path + f\"{prefix}/{audio_path}\")\n", " if os.path.isfile(balanced_audio_path + f\"{prefix}/{audio_path}\" ):\n", " found+=1\n", " available_files.append(meta_csv['audio_name'][n])\n", " available_targets.append(meta_csv['target'][n])\n", " else:\n", " notfound+=1\n", " print(f\"Found {found} . not found {notfound}\")\n", " return available_files,available_targets\n", "# %%\n", "\n", "# %%\n", "\n", "# %%\n", "\n", "\n", "os.makedirs(os.path.dirname(base_dir + \"mp3\"), exist_ok=True)\n", "\n", "for read_file,prefix in [(balanced_csv,\"balanced_train_segments/\"), (eval_csv,\"eval_segments/\"),]:\n", " print(\"now working on \",read_file,prefix)\n", " #files, y = torch.load(read_file+\".pth\")\n", " files, y = check_available(read_file, mp3_path, prefix)\n", " y = np.packbits(y, axis=-1)\n", " packed_len = y.shape[1]\n", " print(files[0], \"classes: \",packed_len, y.dtype)\n", " available_size = len(files)\n", " f = files[0][:-3]+\"mp3\"\n", " a = np.fromfile(mp3_path+prefix + \"/\"+f, dtype='uint8')\n", "\n", " dt = h5py.vlen_dtype(np.dtype('uint8'))\n", " save_file = prefix.split(\"/\")[0]\n", " os.makedirs(os.path.dirname(base_dir + \"mp3/\" ), exist_ok=True)\n", " with h5py.File(base_dir+ \"mp3/\" + save_file+\"_mp3.hdf\", 'w') as hf:\n", " audio_name = hf.create_dataset('audio_name', shape=(0,), maxshape=(None,), dtype='S20')\n", " waveform = hf.create_dataset('mp3', shape=(0,), maxshape=(None,), dtype=dt)\n", " target = hf.create_dataset('target', shape=(0, packed_len), maxshape=(None, packed_len), dtype=y.dtype)\n", " for i,file in enumerate(files):\n", " if i%1000==0:\n", " print(f\"{i}/{available_size}\")\n", " f = file[:-3] + \"mp3\"\n", " a = np.fromfile(mp3_path + prefix + f, dtype='uint8')\n", " try:\n", " # Kiểm tra xem file audio có đọc được không\n", " decode_mp3(a) # Dùng hàm decode_mp3 của bạn\n", "\n", " audio_name.resize((i + 1,))\n", " waveform.resize((i + 1,))\n", " target.resize((i + 1, packed_len))\n", "\n", " audio_name[i]=f\n", " waveform[i] = a\n", " target[i] = y[i]\n", " except Exception as e:\n", " print(f\"File lỗi tại index {i} với file {file}: {e}\")\n", "\n", " print(a.shape)\n", " print(\"Done!\" , prefix)" ], "metadata": { "id": "8oFKEbtb5mzr" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "##For this structure folder/train/folder(class)/file" ], "metadata": { "id": "mCwcSx8y5v7q" } }, { "cell_type": "markdown", "source": [ "![image.png](data:image/png;base64,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)" ], "metadata": { "id": "cRAr5tkn566K" } }, { "cell_type": "code", "source": [ "import h5py\n", "import numpy as np\n", "import os\n", "import io\n", "import av\n", "from pathlib import Path\n", "from tqdm import tqdm\n", "\n", "def decode_mp3(mp3_arr):\n", " \"\"\"\n", " Giải mã một mảng uint8 đại diện cho một file MP3.\n", " :rtype: np.array\n", " \"\"\"\n", " try:\n", " container = av.open(io.BytesIO(mp3_arr.tobytes()))\n", " stream = next(s for s in container.streams if s.type == 'audio')\n", " a = []\n", " for packet in container.demux(stream):\n", " for frame in packet.decode():\n", " a.append(frame.to_ndarray().reshape(-1))\n", " waveform = np.concatenate(a)\n", " if waveform.dtype != 'float32':\n", " raise RuntimeError(\"Unexpected wave type\")\n", " return waveform\n", " except Exception as e:\n", " raise RuntimeError(f\"Cannot decode MP3: {e}\")\n", "\n", "def scan_dataset_structure(dataset_path):\n", " \"\"\"\n", " Quét cấu trúc thư mục dataset và tạo mapping cho classes\n", " Structure: dataset_path/train(or test)/class_name/*.mp3\n", " \"\"\"\n", " dataset_path = Path(dataset_path)\n", "\n", " # Lấy tất cả các class names từ thư mục train\n", " train_path = dataset_path / \"train\"\n", " if not train_path.exists():\n", " raise ValueError(f\"Train folder not found: {train_path}\")\n", "\n", " classes = sorted([d.name for d in train_path.iterdir() if d.is_dir()])\n", " classes_num = len(classes)\n", "\n", " # Tạo mapping\n", " lb_to_ix = {label: i for i, label in enumerate(classes)}\n", " ix_to_lb = {i: label for i, label in enumerate(classes)}\n", "\n", " print(f\"Found {classes_num} classes: {classes[:7]}...\" if len(classes) > 7 else f\"Found {classes_num} classes: {classes}\")\n", "\n", " return classes, classes_num, lb_to_ix, ix_to_lb\n", "\n", "def collect_audio_files(dataset_path, split='train', shuffle=True, random_seed=42):\n", " \"\"\"\n", " Thu thập tất cả audio files từ structure thư mục và shuffle để tránh grouping theo class\n", " \"\"\"\n", " dataset_path = Path(dataset_path)\n", " split_path = dataset_path / split\n", "\n", " if not split_path.exists():\n", " raise ValueError(f\"{split} folder not found: {split_path}\")\n", "\n", " audio_files = []\n", " labels = []\n", " class_counts = {}\n", "\n", " class_dirs = [d for d in split_path.iterdir() if d.is_dir()]\n", "\n", " print(f\"📁 Scanning {split} folder...\")\n", " for class_dir in tqdm(class_dirs, desc=f\"Scanning classes\"):\n", " class_name = class_dir.name\n", " mp3_files = list(class_dir.glob(\"*.mp3\"))\n", " class_counts[class_name] = len(mp3_files)\n", "\n", " for mp3_file in mp3_files:\n", " audio_files.append(str(mp3_file))\n", " labels.append(class_name)\n", "\n", " # Shuffle để tránh việc group theo class trong HDF5\n", " if shuffle:\n", " import random\n", " random.seed(random_seed)\n", "\n", " # Zip files và labels lại, sau đó shuffle\n", " combined = list(zip(audio_files, labels))\n", " random.shuffle(combined)\n", "\n", " # Unpack lại\n", " audio_files, labels = zip(*combined)\n", " audio_files = list(audio_files)\n", " labels = list(labels)\n", "\n", " print(f\"🔀 Files shuffled with seed={random_seed}\")\n", "\n", " # In class distribution\n", " print(f\"✅ Found {len(audio_files)} audio files in {split} set\")\n", " print(f\"📊 Class distribution:\")\n", " for class_name, count in sorted(class_counts.items()):\n", " percentage = count / len(audio_files) * 100\n", " print(f\" {class_name}: {count} files ({percentage:.1f}%)\")\n", "\n", " return audio_files, labels\n", "\n", "def create_target_array(labels, classes_num, lb_to_ix):\n", " \"\"\"\n", " Tạo target array từ danh sách labels\n", " \"\"\"\n", " targets = []\n", " for label in labels:\n", " target = np.zeros(classes_num, dtype=bool)\n", " if label in lb_to_ix:\n", " ix = lb_to_ix[label]\n", " target[ix] = 1\n", " targets.append(target)\n", "\n", " return np.array(targets)\n", "\n", "def convert_to_hdf5(dataset_path, output_dir):\n", " \"\"\"\n", " Convert audio dataset to HDF5 format\n", " \"\"\"\n", " # Tạo output directory\n", " os.makedirs(output_dir, exist_ok=True)\n", "\n", " # Quét cấu trúc dataset\n", " classes, classes_num, lb_to_ix, ix_to_lb = scan_dataset_structure(dataset_path)\n", "\n", " # Process both train and test splits\n", " for split in ['train', 'test']:\n", " print(f\"\\n=== Processing {split} set ===\")\n", "\n", " try:\n", " # Thu thập audio files\n", " audio_files, labels = collect_audio_files(dataset_path, split)\n", "\n", " if len(audio_files) == 0:\n", " print(f\"No audio files found in {split} set, skipping...\")\n", " continue\n", "\n", " # Tạo target array\n", " targets = create_target_array(labels, classes_num, lb_to_ix)\n", "\n", " # Pack targets để tiết kiệm memory\n", " packed_targets = np.packbits(targets, axis=-1)\n", " packed_len = packed_targets.shape[1]\n", "\n", " print(f\"Target shape: {targets.shape} -> Packed: {packed_targets.shape}\")\n", "\n", " # Tạo HDF5 file\n", " dt = h5py.vlen_dtype(np.dtype('uint8'))\n", " hdf5_path = os.path.join(output_dir, f\"{split}_mp3.hdf5\")\n", "\n", " with h5py.File(hdf5_path, 'w') as hf:\n", " # Tạo datasets\n", " audio_name_ds = hf.create_dataset('audio_name', shape=(0,), maxshape=(None,), dtype='S200')\n", " waveform_ds = hf.create_dataset('mp3', shape=(0,), maxshape=(None,), dtype=dt)\n", " target_ds = hf.create_dataset('target', shape=(0, packed_len), maxshape=(None, packed_len), dtype=packed_targets.dtype)\n", "\n", " # Lưu class info\n", " hf.attrs['classes'] = [c.encode('utf-8') for c in classes]\n", " hf.attrs['classes_num'] = classes_num\n", "\n", " valid_count = 0\n", " error_count = 0\n", "\n", " # Process từng file với tqdm\n", " pbar = tqdm(zip(audio_files, labels),\n", " total=len(audio_files),\n", " desc=f\"Converting {split}\")\n", "\n", " for i, (audio_file, label) in enumerate(pbar):\n", " try:\n", " # Đọc file MP3\n", " audio_data = np.fromfile(audio_file, dtype='uint8')\n", "\n", " # Kiểm tra tính hợp lệ bằng cách decode\n", " decode_mp3(audio_data)\n", "\n", " # Resize datasets\n", " audio_name_ds.resize((valid_count + 1,))\n", " waveform_ds.resize((valid_count + 1,))\n", " target_ds.resize((valid_count + 1, packed_len))\n", "\n", " # Lưu data\n", " filename = os.path.basename(audio_file).encode('utf-8')\n", " audio_name_ds[valid_count] = filename\n", " waveform_ds[valid_count] = audio_data\n", " target_ds[valid_count] = packed_targets[i]\n", "\n", " valid_count += 1\n", "\n", " # Update progress bar\n", " pbar.set_postfix({\n", " 'Valid': valid_count,\n", " 'Errors': error_count,\n", " 'Success Rate': f\"{valid_count/(i+1)*100:.1f}%\"\n", " })\n", "\n", " except Exception as e:\n", " error_count += 1\n", " pbar.set_postfix({\n", " 'Valid': valid_count,\n", " 'Errors': error_count,\n", " 'Success Rate': f\"{valid_count/(i+1)*100:.1f}%\"\n", " })\n", " if error_count <= 5: # Chỉ show 5 error đầu tiên\n", " tqdm.write(f\"❌ Error processing {os.path.basename(audio_file)}: {e}\")\n", " continue\n", "\n", " pbar.close()\n", "\n", " print(f\"Successfully processed {valid_count}/{len(audio_files)} files\")\n", " print(f\"Saved to: {hdf5_path}\")\n", "\n", " except Exception as e:\n", " print(f\"Error processing {split} set: {e}\")\n", "\n", "def main():\n", " # Cấu hình paths\n", " dataset_path = \"/content/dataset\" # Thay đổi path này\n", " output_dir = \"/content/dataset_hdf5\" # Thay đổi path này\n", "\n", " # Chạy conversion\n", " convert_to_hdf5(dataset_path, output_dir)\n", " print(\"\\n=== Conversion completed! ===\")\n", "\n", "if __name__ == \"__main__\":\n", " # Example usage:\n", " # dataset_path = \"/content/audio_dataset\"\n", " # output_dir = \"/content/output_hdf5\"\n", " # convert_to_hdf5(dataset_path, output_dir)\n", " main()" ], "metadata": { "id": "lcdNaKMx59ip" }, "execution_count": null, "outputs": [] } ] }