{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d31d8850",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:37:41.284627Z",
     "start_time": "2024-06-22T03:37:41.283149Z"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "7cd4c0dd",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:37:43.925704Z",
     "start_time": "2024-06-22T03:37:41.285502Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2420412/2837018412.py:13: DeprecationWarning: \n",
      "Pyarrow will become a required dependency of pandas in the next major release of pandas (pandas 3.0),\n",
      "(to allow more performant data types, such as the Arrow string type, and better interoperability with other libraries)\n",
      "but was not found to be installed on your system.\n",
      "If this would cause problems for you,\n",
      "please provide us feedback at https://github.com/pandas-dev/pandas/issues/54466\n",
      "        \n",
      "  import pandas as pd\n",
      "/home/tony/anaconda3/envs/suno_env/lib/python3.10/site-packages/Bio/pairwise2.py:278: BiopythonDeprecationWarning: Bio.pairwise2 has been deprecated, and we intend to remove it in a future release of Biopython. As an alternative, please consider using Bio.Align.PairwiseAligner as a replacement, and contact the Biopython developers if you still need the Bio.pairwise2 module.\n",
      "  warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "import tqdm\n",
    "import math\n",
    "import torch\n",
    "import random\n",
    "import funcy\n",
    "import copy\n",
    "import gc\n",
    "import re\n",
    "import json\n",
    "import tempfile\n",
    "import collections\n",
    "from collections import Counter\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import fasttext\n",
    "from joblib import Parallel, delayed\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from suno_utils.audio import Audio\n",
    "from suno_utils.utils.text import (\n",
    "    write_jsonl,\n",
    "    read_jsonl,\n",
    "    write_json,\n",
    "    read_json,\n",
    "    normalize_whitespace,\n",
    ")\n",
    "from suno_utils.utils.lyrics import remove_speakers\n",
    "from suno_utils.utils.s3 import read_from_s3, check_s3_file_exists, open_from_s3\n",
    "from suno_utils.utils.tokenizers import tokenize\n",
    "from suno_utils.harvest.youtube.constants.text_lang import BASE_TO_FASTTEXT_REMAP\n",
    "from Bio import pairwise2\n",
    "from suno_utils.utils.metrics import get_cer\n",
    "from suno_utils.tasks.hoot import (\n",
    "    parse_lyrics,\n",
    "    legacy_parse_lyrics,\n",
    "    EMBEDDING_RATE as HOOT_EMBEDDING_RATE,\n",
    ")\n",
    "from suno_utils.utils.lyrics import remove_speakers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d6518a0b",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:37:45.582960Z",
     "start_time": "2024-06-22T03:37:43.927818Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Warning : `load_model` does not return WordVectorModel or SupervisedModel any more, but a `FastText` object which is very similar.\n"
     ]
    }
   ],
   "source": [
    "LANG_ID_MODEL_FP = \"s3://suno-data/georg/trained_models/chirp_v1/lid.176.bin\"\n",
    "text_lang_model = read_from_s3(LANG_ID_MODEL_FP, read_f=fasttext.load_model)\n",
    "\n",
    "\n",
    "def _get_text_lang(text):\n",
    "    \"\"\"get probability of input language for text\"\"\"\n",
    "    text = text.replace(\"’\", \"'\").lower()\n",
    "    text = re.sub(r\"\\[.+?\\]\", \" \", text)\n",
    "    text = normalize_whitespace(text)\n",
    "    out = text_lang_model.predict(text, k=1)\n",
    "    lang_str = out[0][0]\n",
    "    p_lang = out[1][0]\n",
    "    lang = lang_str.split(\"__\")[-1]\n",
    "    lang = BASE_TO_FASTTEXT_REMAP.get(lang, lang)\n",
    "    #     if p_lang >= 0.8:\n",
    "    #         return lang\n",
    "    return p_lang, lang\n",
    "\n",
    "\n",
    "TMP_DIR = os.path.join(os.getcwd(), \"hoot\")\n",
    "os.makedirs(TMP_DIR, exist_ok=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d9d50793",
   "metadata": {},
   "source": [
    "## load genius_hq info"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "2cd505d5",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:37:55.552314Z",
     "start_time": "2024-06-22T03:37:45.584921Z"
    }
   },
   "outputs": [],
   "source": [
    "# takes ~ 2 mins\n",
    "base_metas = read_jsonl(\"/app/suno/tmp/clean_youtube_music_v0_metas.jsonl\")\n",
    "# TODO: original IDs are already unique here, but did we resolve correctly by highest genius views?\n",
    "#   could be a way to filter translations that don't contain the word 'translation'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c6ae4949",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:37:55.559003Z",
     "start_time": "2024-06-22T03:37:55.554189Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'id': 'trzoLkjVu4s',\n",
       " 'views': 60158,\n",
       " 'duration_s': 125,\n",
       " 'tags': ['hip-hop', 'commute'],\n",
       " 'private_tags': ['commute',\n",
       "  'Free 03',\n",
       "  'Took A Little Minute',\n",
       "  'hip-hop',\n",
       "  '03 Greedo;Mike Free'],\n",
       " 'text': \"Yo, yo, yo, uh\\nNo free features\\nIt's the 03, Mike Free shit\\nYeah\\n\\nTook a lil minute but I had to get it\\nThese haters ain't stopping shit\\nBitch I'm committed, don't go to hospitals unless I'm admitted\\nDon't go to no churches cause I ain't a christian\\nThugging is all of my niggas religion\\nBetween my eyes, I'm having visions\\n\\nBitch I do Voodoo, my bitches are witches\\nGot sweat on my palms and my fingers is itchy\\nCan't trust these hittas, some killers be snitching\\nFly ass young nigga from the got vision\\nThis for my niggas with purple\\nRemember my niggas for smoking that\\nWe were OT with the purple for flipping\\nHang wit the squares and pull up on these niggas like I was Steve Urkle\\nWe lurking with fifties, when they hit it\\n\\nCome with the drum for a remix, sellin them rollers like\",\n",
       " 'lang': 'en',\n",
       " 'audio_filepath': 's3://suno-data/datasets/harvest/youtube_music/audio/trzoLkjVu4s.webm',\n",
       " 'original_id': 'trzoLkjVu4s'}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "base_metas[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "251edcf4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:37:56.125732Z",
     "start_time": "2024-06-22T03:37:55.560327Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total, 724608\n",
      "lang cut, 0\n",
      "youtube view cut, 0\n",
      "duration cut, 6658\n",
      "lyrics cut, 919\n"
     ]
    }
   ],
   "source": [
    "total_base_metas = len(base_metas)\n",
    "n_genius_view_cut = 5\n",
    "n_youtube_view_cut = 1000\n",
    "max_duration = 8 * 60\n",
    "min_duration = 1 * 60\n",
    "max_len_lyrics = 9128\n",
    "min_len_lyrics = 64\n",
    "print(f\"total, {len(base_metas)}\")\n",
    "print(f\"lang cut, {sum(1 if m['lang'] is None else 0 for m in base_metas)}\")\n",
    "print(\n",
    "    f'youtube view cut, {sum(1 if m[\"views\"] < n_youtube_view_cut else 0 for m in base_metas)}'\n",
    ")\n",
    "print(\n",
    "    f'duration cut, {sum(1 if (m[\"duration_s\"] > max_duration or m[\"duration_s\"] < min_duration) else 0 for m in base_metas)}'\n",
    ")\n",
    "print(\n",
    "    f'lyrics cut, {sum(1 if (len(m[\"text\"]) > max_len_lyrics or len(m[\"text\"]) < min_len_lyrics) else 0 for m in base_metas)}'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6ac295a0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:37:58.081465Z",
     "start_time": "2024-06-22T03:37:56.128180Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "724608 clips\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████| 724608/724608 [00:01<00:00, 421013.86it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "717143 filtered clips\n",
      "45313 hours\n"
     ]
    }
   ],
   "source": [
    "print(len(base_metas), \"clips\")\n",
    "metas = []\n",
    "seen_id = set()\n",
    "seen_path = set()\n",
    "for m in tqdm.tqdm(base_metas):\n",
    "    # guessed_lang = _get_text_lang(m[\"lyrics\"])[1]\n",
    "    if (\n",
    "        m[\"views\"] < n_youtube_view_cut\n",
    "        or m[\"lang\"] is None\n",
    "        or any(\"translation\" in tag.lower() for tag in m.get(\"tags\", []))\n",
    "        # or m[\"lang\"].lower()[:2] != \"en\"\n",
    "        or m[\"duration_s\"] < min_duration\n",
    "        or m[\"duration_s\"] > max_duration\n",
    "        or len(m[\"text\"]) < min_len_lyrics\n",
    "        or len(m[\"text\"]) > max_len_lyrics\n",
    "        or m[\"id\"] in seen_id\n",
    "        or m[\"audio_filepath\"] in seen_path\n",
    "        # or _get_text_lang(m[\"lyrics\"])[1] != \"en\"\n",
    "    ):\n",
    "        continue\n",
    "    seen_id.add(m[\"id\"])\n",
    "    seen_path.add(m[\"audio_filepath\"])\n",
    "    new_m = {\n",
    "        \"id\": m[\"id\"],\n",
    "        \"lyrics\": m[\"text\"].strip(),\n",
    "        \"duration_s\": m[\"duration_s\"],\n",
    "        \"lang\": m[\"lang\"],\n",
    "        # \"guess_lang\": guessed_lang,\n",
    "        \"audio_filepath\": m[\"audio_filepath\"],\n",
    "        \"original_id\": m[\"original_id\"],\n",
    "        \"youtube_views\": m[\"views\"],\n",
    "    }\n",
    "    metas.append(new_m)\n",
    "print(len(metas), \"filtered clips\")\n",
    "print(round(sum(m[\"duration_s\"] for m in metas) / 60 / 60), \"hours\")\n",
    "metas_map = {m[\"id\"]: m for m in metas}\n",
    "# 2090009 clips\n",
    "# 1836168 filtered clips\n",
    "# 107025 hours"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "aa66a026",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:37:58.502398Z",
     "start_time": "2024-06-22T03:37:58.083098Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counter({'en': 386682, 'es': 118004, 'pt': 39485, 'fr': 15643, 'ja': 15515, 'ko': 15269, 'tr': 12582, 'zh': 10393, 'de': 10116, 'ru': 9508, 'hi': 9032, 'id': 8619, 'ar': 7495, 'it': 6748, 'pl': 3671, 'th': 2996, 'tl': 2905, 'pa': 2854, 'ta': 2624, 'sr': 2461, 'he': 2433, 'hu': 2099, 'te': 2085, 'nl': 1901, 'uk': 1710, 'fi': 1685, 'el': 1550, 'ro': 1456, 'cs': 1446, 'bn': 1340, 'sv': 1301, 'hr': 1189, 'fa': 1166, 'vi': 948, 'da': 939, 'bg': 698, 'ml': 657, 'kn': 540, 'ca': 529, 'sk': 510, 'mr': 485, 'no': 377, 'ne': 371, 'lt': 297, 'lv': 284, 'ku': 282, 'az': 282, 'uz': 270, 'am': 255, 'eu': 251, 'si': 248, 'or': 245, 'sq': 239, 'ms': 237, 'ur': 231, 'af': 230, 'sl': 226, 'et': 213, 'arz': 184, 'sw': 171, 'mn': 150, 'hy': 148, 'la': 137, 'cy': 135, 'is': 133, 'war': 131, 'jv': 126, 'ka': 126, 'eo': 107, 'my': 100, 'als': 98, 'kk': 92, 'su': 84, 'sh': 82, 'as': 80, 'ht': 79, 'tt': 73, 'ky': 68, 'ga': 61, 'gl': 56, 'ceb': 55, 'gu': 54, 'mk': 52, 'jbo': 52, 'ckb': 48, 'bs': 48, 'nn': 48, 'pnb': 48, 'km': 43, 'be': 42, 'br': 33, 'sa': 27, 'nap': 24, 'yi': 23, 'gd': 23, 'qu': 21, 'kw': 18, 'mg': 15, 'mzn': 14, 'bh': 14, 'mt': 14, 'io': 14, 'ast': 13, 'tk': 12, 'gn': 11, 'ilo': 11, 'oc': 10, 'tg': 10, 'diq': 8, 'pms': 7, 'ia': 7, 'yo': 6, 'fy': 6, 'new': 6, 'lmo': 6, 'sah': 6, 'vec': 6, 'nds': 5, 'scn': 5, 'ce': 4, 'wa': 4, 'eml': 4, 'ba': 4, 'so': 3, 'rm': 2, 'an': 2, 'lb': 2, 'min': 2, 'pam': 2, 'ps': 2, 'sd': 2, 'nah': 2, 'gom': 2, 'tyv': 2, 'lo': 1, 'bcl': 1, 'sc': 1, 'cv': 1, 'cbk': 1, 'sco': 1, 'ug': 1, 'xmf': 1, 'os': 1, 'yue': 1, 'ie': 1})\n"
     ]
    }
   ],
   "source": [
    "c = Counter([m[\"lang\"] for m in metas])\n",
    "print(c)\n",
    "metas_map = {m[\"id\"]: m for m in metas if c[m[\"lang\"]] > 100}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "2b486253",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:38:03.267133Z",
     "start_time": "2024-06-22T03:37:58.504058Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "717143 filtered clips\n",
      "en 386682 24272 hours\n",
      "es 118004 7299 hours\n",
      "pt 39485 2437 hours\n",
      "fr 15643 950 hours\n",
      "ja 15515 1069 hours\n",
      "ko 15269 931 hours\n",
      "tr 12582 839 hours\n",
      "zh 10393 708 hours\n",
      "de 10116 578 hours\n",
      "ru 9508 566 hours\n",
      "hi 9032 687 hours\n",
      "id 8619 634 hours\n",
      "ar 7495 532 hours\n",
      "it 6748 417 hours\n",
      "pl 3671 226 hours\n",
      "th 2996 203 hours\n",
      "tl 2905 208 hours\n",
      "pa 2854 176 hours\n",
      "ta 2624 193 hours\n",
      "sr 2461 149 hours\n",
      "he 2433 152 hours\n",
      "hu 2099 129 hours\n",
      "te 2085 156 hours\n",
      "nl 1901 108 hours\n",
      "uk 1710 100 hours\n",
      "fi 1685 104 hours\n",
      "el 1550 96 hours\n",
      "ro 1456 88 hours\n",
      "cs 1446 88 hours\n",
      "bn 1340 95 hours\n",
      "sv 1301 77 hours\n",
      "hr 1189 77 hours\n",
      "fa 1166 82 hours\n",
      "vi 948 68 hours\n",
      "da 939 54 hours\n",
      "bg 698 43 hours\n",
      "ml 657 46 hours\n",
      "kn 540 40 hours\n",
      "ca 529 32 hours\n",
      "sk 510 31 hours\n",
      "mr 485 35 hours\n",
      "no 377 23 hours\n",
      "ne 371 27 hours\n",
      "lt 297 18 hours\n",
      "lv 284 17 hours\n",
      "ku 282 20 hours\n",
      "az 282 18 hours\n",
      "uz 270 17 hours\n",
      "am 255 22 hours\n",
      "eu 251 16 hours\n",
      "si 248 16 hours\n",
      "or 245 19 hours\n",
      "sq 239 14 hours\n",
      "ms 237 17 hours\n",
      "ur 231 19 hours\n",
      "af 230 14 hours\n",
      "sl 226 14 hours\n",
      "et 213 13 hours\n",
      "arz 184 13 hours\n",
      "sw 171 12 hours\n",
      "mn 150 10 hours\n",
      "hy 148 9 hours\n",
      "la 137 9 hours\n",
      "cy 135 9 hours\n",
      "is 133 10 hours\n",
      "war 131 12 hours\n",
      "jv 126 11 hours\n",
      "ka 126 8 hours\n",
      "eo 107 7 hours\n"
     ]
    }
   ],
   "source": [
    "print(len(metas), \"filtered clips\")\n",
    "c = Counter([m[\"lang\"] for m in metas_map.values()])\n",
    "for k, v in c.most_common():\n",
    "    print(\n",
    "        k,\n",
    "        c[k],\n",
    "        round(sum(m[\"duration_s\"] for m in metas if m[\"lang\"] == k) / 60 / 60),\n",
    "        \"hours\",\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "c2ce5d00",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:38:03.271359Z",
     "start_time": "2024-06-22T03:38:03.269149Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'id': 'HM6igTdc-nk', 'lyrics': '我帶半醉與倦容 徘徊暮色之中\\n呼呼北風可知道 如何覓她芳蹤\\n在我心裡面已經認同\\n從前夜裡情深抱擁\\n為妳一副任性的面容\\n自甘去被戲弄\\n\\n＊祇願一生愛一人\\n因妳是獨有（即使做玩偶）\\n祇願一生愛一人\\n一世亦未夠（求莫要我心傷透）\\n\\n過去愛意那樣濃 為何就此失蹤\\n到了這晚有裂逄 如何共她溝通\\n但妳不再轉身回頭 求求別要提早放手\\n就算拋出了我的所有 亦不理會以後\\n重唱＊', 'duration_s': 256, 'lang': 'zh', 'audio_filepath': 's3://suno-data/datasets/harvest/youtube_music/audio/HM6igTdc-nk.webm', 'original_id': 'HM6igTdc-nk', 'youtube_views': 182789}\n"
     ]
    }
   ],
   "source": [
    "for m in metas:\n",
    "    if m[\"lang\"] == \"zh\":\n",
    "        print(m)\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "346cc768",
   "metadata": {},
   "source": [
    "# Pack the data\n",
    "format to save to:\n",
    "{\"audio_filepath\": \"./an4/wav/an4_clstk/fash/an251-fash-b.wav\", \"duration\": 1.0, \"text\": \"yes\"}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "71df5d56",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:38:03.590615Z",
     "start_time": "2024-06-22T03:38:03.272648Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "724608\n",
      "724608\n"
     ]
    }
   ],
   "source": [
    "# this will also take 2 min...\n",
    "downloaded_files = os.listdir(\"/app/suno/data/hoot_ytm/\")\n",
    "print(len(downloaded_files))\n",
    "downloaded_ids = set([f.replace(\".wav\", \"\") for f in downloaded_files])\n",
    "print(len(downloaded_ids))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c8227733",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:38:03.794241Z",
     "start_time": "2024-06-22T03:38:03.592579Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "717143\n"
     ]
    }
   ],
   "source": [
    "subset_meta = [\n",
    "    m for m in metas if (m[\"original_id\"] in downloaded_ids)\n",
    "]  # and m[\"lang\"] == \"en\")]\n",
    "print(len(subset_meta))\n",
    "# 986464"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "2f9e4207",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:38:03.799643Z",
     "start_time": "2024-06-22T03:38:03.795777Z"
    }
   },
   "outputs": [],
   "source": [
    "RE_EMOJI = re.compile(\"[\\U00010000-\\U0010ffff]\", flags=re.UNICODE)\n",
    "\n",
    "\n",
    "def clean_text(text):\n",
    "    \"\"\"General text cleaning. A bit tight but makes the content very clean.\"\"\"\n",
    "    text = \"\\n\" + text\n",
    "    text = RE_EMOJI.sub(r\"\", text)  # remove emojis\n",
    "    text = text.replace(\"’\", \"'\").lower()\n",
    "    text = text.replace('\"', \"\").lower()\n",
    "    text = re.sub(r\"\\[.+?\\]\", \" \", text)  # tags\n",
    "    text = re.sub(r\"\\n.+?\\:\", \" \", text)  # new line ends with :\n",
    "    text = re.sub(r\"\\n.+?\\：\", \" \", text)  # new line ends with :\n",
    "    text = re.sub(r\"\\n\\(.+?\\)\", \" \", text)  # new line with ()\n",
    "    text = re.sub(r\"[\\d]\", \" \", text)  # digits\n",
    "    text = re.sub(r\"▁\", \"\", text)  # special stuff\n",
    "    text = remove_speakers(text)\n",
    "    text = re.sub(r\"[^\\w\\'\\s]\", \" \", text)  # keep only the words\n",
    "    text = normalize_whitespace(text)\n",
    "    return text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "0d2555e3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:38:03.862327Z",
     "start_time": "2024-06-22T03:38:03.800928Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Yo, yo, yo, uh\n",
      "No free features\n",
      "It's the 03, Mike Free shit\n",
      "Yeah\n",
      "\n",
      "Took a lil minute but I had to get it\n",
      "These haters ain't stopping shit\n",
      "Bitch I'm committed, don't go to hospitals unless I'm admitted\n",
      "Don't go to no churches cause I ain't a christian\n",
      "Thugging is all of my niggas religion\n",
      "Between my eyes, I'm having visions\n",
      "\n",
      "Bitch I do Voodoo, my bitches are witches\n",
      "Got sweat on my palms and my fingers is itchy\n",
      "Can't trust these hittas, some killers be snitching\n",
      "Fly ass young nigga from the got vision\n",
      "This for my niggas with purple\n",
      "Remember my niggas for smoking that\n",
      "We were OT with the purple for flipping\n",
      "Hang wit the squares and pull up on these niggas like I was Steve Urkle\n",
      "We lurking with fifties, when they hit it\n",
      "\n",
      "Come with the drum for a remix, sellin them rollers like\n",
      "-------\n",
      "yo yo yo uh no free features it's the mike free shit yeah took a lil minute but i had to get it these haters ain't stopping shit bitch i'm committed don't go to hospitals unless i'm admitted don't go to no churches cause i ain't a christian thugging is all of my niggas religion between my eyes i'm having visions bitch i do voodoo my bitches are witches got sweat on my palms and my fingers is itchy can't trust these hittas some killers be snitching fly ass young nigga from the got vision this for my niggas with purple remember my niggas for smoking that we were ot with the purple for flipping hang wit the squares and pull up on these niggas like i was steve urkle we lurking with fifties when they hit it come with the drum for a remix sellin them rollers like\n"
     ]
    }
   ],
   "source": [
    "# Quality checks\n",
    "n_c = 0\n",
    "for m in metas:\n",
    "    if m[\"lang\"] == \"en\":\n",
    "        n_c += 1\n",
    "        if n_c == 1:\n",
    "            text = m[\"lyrics\"]\n",
    "            print(text)\n",
    "            print(\"-------\")\n",
    "            print(clean_text(text))\n",
    "            break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "e8b679e7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:38:03.947516Z",
     "start_time": "2024-06-22T03:38:03.863568Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sentencepiece\n",
    "\n",
    "tokenizer = sentencepiece.SentencePieceProcessor()\n",
    "tokenizer.load(\"./tokenizers/full/tokenizer_spe_bpe_v20480/tokenizer.model\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "feacb5f1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T03:38:04.474439Z",
     "start_time": "2024-06-22T03:38:03.949099Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "717143 717143\n"
     ]
    }
   ],
   "source": [
    "print(len(subset_meta), len(set(m[\"original_id\"] for m in subset_meta)))\n",
    "random.shuffle(subset_meta)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "3a3246ca",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:00:32.774980Z",
     "start_time": "2024-06-22T03:38:04.476001Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████| 717143/717143 [22:28<00:00, 531.92it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total 690732, too long: 10651, text too short: 25, text too long: 21, text bad: 15714\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "info = []\n",
    "n_text_too_short = 0\n",
    "n_text_too_long = 0\n",
    "n_audio_too_long = 0\n",
    "n_lang = collections.defaultdict(int)\n",
    "n_repeat_ratio_too_high = 0\n",
    "n_lang_max_cut = 5_000_000  # 10k songs :D, 2_000_000 is max\n",
    "bad_meta_ids = []\n",
    "for meta in tqdm.tqdm(subset_meta):\n",
    "    output_path = os.path.join(\"/app/suno/data/hoot_ytm\", f\"{meta['original_id']}.wav\")\n",
    "    if (\n",
    "        meta[\"duration_s\"] > 400\n",
    "    ):  # this cut is mainly for batching purposes...X.x, but...we probably shouldn't have this.\n",
    "        n_audio_too_long += 1\n",
    "        continue\n",
    "    n_lang[meta[\"lang\"]] += 1\n",
    "    if n_lang[meta[\"lang\"]] > n_lang_max_cut:\n",
    "        continue\n",
    "    cleaned_text = clean_text(meta[\"lyrics\"])\n",
    "    # cleaned_text = meta[\"lyrics\"].lower() # clean_text(meta[\"lyrics\"])\n",
    "    #     cleaned_tokens = tokenizer.encode(cleaned_text)\n",
    "    #     decoded_tokens = tokenizer.decode(cleaned_tokens)\n",
    "    #     if decoded_tokens != cleaned_text:\n",
    "    #         print(cleaned_text)\n",
    "    #         print(decoded_tokens)\n",
    "    if len(cleaned_text) < 20:\n",
    "        n_text_too_short += 1\n",
    "        continue\n",
    "    # check the high freq token frequency\n",
    "    encoded_array = np.array(tokenizer.encode(cleaned_text))\n",
    "    if len(encoded_array) > meta[\"duration_s\"] * 12:\n",
    "        n_text_too_long += 1\n",
    "        continue\n",
    "    repeat_ratio = max(np.bincount(encoded_array)) / (encoded_array.shape[0] + 1)\n",
    "    if repeat_ratio > 0.3:\n",
    "        n_repeat_ratio_too_high += 1\n",
    "        bad_meta_ids.append(meta[\"id\"])\n",
    "        continue\n",
    "    info.append(\n",
    "        {\n",
    "            \"audio_filepath\": output_path,\n",
    "            \"duration\": meta[\"duration_s\"],\n",
    "            \"text\": cleaned_text,\n",
    "            \"lyrics\": meta[\"lyrics\"],\n",
    "            \"lang\": meta[\"lang\"],\n",
    "            \"id\": meta[\"id\"],\n",
    "            \"genius_views\": meta.get(\"genius_views\", 0),\n",
    "            \"youtube_views\": meta.get(\"youtube_views\", 0),\n",
    "        }\n",
    "    )\n",
    "    if not os.path.exists(output_path):\n",
    "        # print(\"WTF\", output_path)\n",
    "        continue\n",
    "#     audio = Audio.from_s3(meta[\"audio_filepath\"])\n",
    "#     audio = audio.convert(16_000, audio.byte_width, n_channels=1)\n",
    "#     audio.to_wav(output_path)\n",
    "print(\n",
    "    f\"total {len(info)}, too long: {n_audio_too_long}, text too short: {n_text_too_short}, text too long: {n_text_too_long}, text bad: {n_repeat_ratio_too_high}\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "618075a0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:00:33.336099Z",
     "start_time": "2024-06-22T04:00:32.776242Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total duration khr 42.95104805555555 60 400 26 8949\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    \"total duration khr\",\n",
    "    sum(m[\"duration\"] for m in info) / 3600000,\n",
    "    min(m[\"duration\"] for m in info),\n",
    "    max(m[\"duration\"] for m in info),\n",
    "    min(len(m[\"text\"]) for m in info),\n",
    "    max(len(m[\"text\"]) for m in info),\n",
    ")\n",
    "# 29.15879888888889 120 100 2879\n",
    "# cut on durations 400: total duration khr 88.80962305555556 60 480 100 5616\n",
    "# cut on 240: total duration khr 54.709809444444446 60 240 100 2880"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "d8eb67a9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:00:33.613282Z",
     "start_time": "2024-06-22T04:00:33.338941Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "688732 2000\n"
     ]
    }
   ],
   "source": [
    "cutoff = -2000\n",
    "random.shuffle(info)\n",
    "train_info = info[:cutoff]\n",
    "test_info = info[cutoff:]\n",
    "print(len(train_info), len(test_info))\n",
    "# 545838 1000"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1642e3b5",
   "metadata": {},
   "source": [
    "# 2nd round of hoot data prep setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "52f2a9a1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:00:33.814362Z",
     "start_time": "2024-06-22T04:00:33.614603Z"
    }
   },
   "outputs": [],
   "source": [
    "metas_map = {m[\"id\"]: m for m in base_metas}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "274e39d7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:41.731679Z",
     "start_time": "2024-06-22T04:00:33.815830Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████| 7247/7247 [03:07<00:00, 38.57it/s]\n"
     ]
    }
   ],
   "source": [
    "from collections import defaultdict\n",
    "\n",
    "total_infos_2 = dict()\n",
    "lang_cers = defaultdict(list)\n",
    "for i in tqdm.tqdm(range(0, len(metas_map), 100)):\n",
    "    try:\n",
    "        with open(\n",
    "            f\"/home/tony/Data/Hoot/alignments/outputs_3_ytm/batch_{i}.json\", \"r\"\n",
    "        ) as fp:\n",
    "            infos = json.load(fp)\n",
    "        for x_info in infos:\n",
    "            if x_info[\"id\"] in total_infos_2:\n",
    "                break\n",
    "            if x_info[\"id\"] not in metas_map:\n",
    "                continue\n",
    "            # if x_info[\"id\"] not in metas_map:\n",
    "            # this is somehow already filtered out...?\n",
    "            total_infos_2[x_info[\"id\"]] = x_info[\"cer_val\"]\n",
    "            lang_cers[metas_map[x_info[\"id\"]][\"lang\"]].append(x_info[\"cer_val\"])\n",
    "    except:\n",
    "        print(\"WTF,\", i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "033dc016",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:41.736477Z",
     "start_time": "2024-06-22T04:03:41.732955Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(724480, 145)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(total_infos_2), len(lang_cers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "ca6fcca0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:41.938159Z",
     "start_time": "2024-06-22T04:03:41.737462Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "lang n_songs median cer\n",
      "en 391680 0.189\n",
      "es 118733 0.13\n",
      "pt 39930 0.17\n",
      "fr 15748 0.237\n",
      "ja 15568 0.354\n",
      "ko 15293 0.221\n",
      "tr 12617 0.134\n",
      "zh 10417 0.443\n",
      "de 10162 0.188\n",
      "ru 9537 0.135\n",
      "hi 9197 1.0\n",
      "id 8658 0.213\n",
      "ar 7744 0.405\n",
      "it 6787 0.141\n",
      "pl 3676 0.13\n",
      "th 2995 0.92\n",
      "tl 2933 0.268\n",
      "pa 2858 0.984\n",
      "ta 2625 1.0\n",
      "sr 2463 0.161\n",
      "he 2441 0.184\n",
      "hu 2104 0.288\n",
      "te 2100 1.0\n",
      "nl 1914 0.262\n",
      "uk 1712 0.304\n",
      "fi 1696 0.242\n",
      "el 1550 0.998\n",
      "ro 1457 0.258\n",
      "cs 1450 0.225\n",
      "bn 1351 1.0\n",
      "sv 1312 0.278\n",
      "hr 1191 0.156\n",
      "fa 1185 0.27\n",
      "vi 951 0.291\n",
      "da 944 0.297\n",
      "bg 698 0.332\n",
      "ml 659 1.0\n",
      "kn 544 1.0\n",
      "ca 532 0.346\n",
      "sk 511 0.24\n",
      "mr 496 1.0\n",
      "no 387 0.352\n",
      "ne 380 1.0\n",
      "lt 297 0.457\n",
      "lv 288 0.384\n",
      "ku 284 0.738\n",
      "az 284 0.206\n",
      "uz 272 0.595\n",
      "am 261 1.0\n",
      "ur 259 1.0\n",
      "eu 253 0.533\n",
      "or 248 1.0\n",
      "si 245 1.0\n",
      "sq 243 0.394\n",
      "ms 241 0.396\n",
      "sl 232 0.382\n",
      "af 231 0.362\n",
      "et 216 0.394\n",
      "arz 194 0.464\n",
      "sw 176 0.471\n",
      "mn 151 0.982\n",
      "hy 147 1.0\n",
      "is 146 0.82\n",
      "war 145 0.648\n",
      "la 144 0.79\n",
      "cy 139 0.724\n",
      "jv 127 0.51\n",
      "ka 125 1.0\n",
      "eo 111 0.672\n",
      "als 98 0.668\n",
      "my 96 1.0\n",
      "kk 92 0.996\n",
      "su 88 0.552\n",
      "sh 82 0.334\n",
      "as 80 1.0\n",
      "ht 79 0.7\n",
      "tt 73 0.997\n",
      "ky 68 0.999\n",
      "ga 61 0.898\n",
      "gl 60 0.5\n",
      "gu 58 1.0\n",
      "ceb 57 0.447\n",
      "jbo 56 0.814\n",
      "mk 52 0.596\n",
      "pnb 52 1.0\n",
      "ckb 51 0.936\n",
      "nn 51 0.396\n",
      "bs 48 0.494\n",
      "km 44 0.998\n",
      "be 42 0.801\n",
      "sa 35 1.0\n",
      "br 34 0.76\n",
      "yi 25 0.814\n",
      "nap 24 0.634\n",
      "gd 23 0.961\n",
      "qu 21 0.527\n",
      "kw 18 0.645\n",
      "mg 15 0.652\n",
      "mzn 15 0.59\n",
      "ast 14 0.626\n",
      "bh 14 1.0\n",
      "mt 14 0.712\n",
      "io 14 0.621\n",
      "tk 12 0.554\n",
      "gn 11 0.664\n",
      "ilo 11 0.584\n",
      "oc 10 0.801\n",
      "tg 10 0.987\n",
      "pms 8 0.763\n",
      "ia 8 0.752\n",
      "diq 8 0.87\n",
      "lmo 7 0.966\n",
      "yo 6 0.705\n",
      "fy 6 0.558\n",
      "new 6 1.0\n",
      "nds 6 0.634\n",
      "sah 6 1.0\n",
      "vec 6 0.611\n",
      "scn 6 0.827\n",
      "wa 5 0.722\n",
      "ce 4 0.981\n",
      "lb 4 0.923\n",
      "eml 4 0.665\n",
      "ba 4 1.0\n",
      "so 3 0.329\n",
      "min 3 0.406\n",
      "rm 2 0.786\n",
      "an 2 0.666\n",
      "pam 2 0.552\n",
      "ps 2 0.94\n",
      "sd 2 0.756\n",
      "nah 2 0.476\n",
      "gom 2 0.89\n",
      "tyv 2 1.0\n"
     ]
    }
   ],
   "source": [
    "langs = [(k, len(v)) for k, v in lang_cers.items()]\n",
    "langs.sort(key=lambda x: (-x[1]))\n",
    "print(\"lang n_songs median cer\")\n",
    "cer_percentage_threshold = 0.5\n",
    "langs_cer_cut = {}\n",
    "for k, l_v in langs:\n",
    "    v = lang_cers[k]\n",
    "    if l_v > 1:\n",
    "        print(k, l_v, round(np.quantile(v, cer_percentage_threshold), 3))\n",
    "        langs_cer_cut[k] = round(np.quantile(v, cer_percentage_threshold), 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "768780a2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:52.219491Z",
     "start_time": "2024-06-22T04:03:41.939518Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████| 724480/724480 [00:10<00:00, 70498.64it/s]\n"
     ]
    }
   ],
   "source": [
    "rates = []\n",
    "cers = []\n",
    "# youtube_views_log = []\n",
    "for k in tqdm.tqdm(total_infos_2):\n",
    "    duration_s = metas_map[k][\"duration_s\"]\n",
    "    n_lyrics = len(metas_map[k][\"text\"].split())\n",
    "    # print(n_lyrics / duration_s)\n",
    "    cers.append(total_infos_2[k])\n",
    "    rates.append(n_lyrics / duration_s)\n",
    "    # youtube_views_log.append(np.log10(metas_map[k][\"youtube_views\"]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "416b615d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:52.522947Z",
     "start_time": "2024-06-22T04:03:52.220744Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.clf()\n",
    "h = plt.hist2d(cers, rates, bins=100)\n",
    "plt.colorbar(h[3])\n",
    "plt.ylim(0, 4)\n",
    "# plt.xlim(0, 0.99)\n",
    "plt.xlabel(\"cer\")\n",
    "plt.ylabel(\"n_words / sec  -- higher faster\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "2172be9d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:54.125887Z",
     "start_time": "2024-06-22T04:03:52.524352Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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fXZDkGkNlhY/79hpeuSzsMsuaTbY1q1bLafTaRUVFVnvvfee9dxzz1lxcXGW3++3LMuyZs2aZeXn59v1b775phUdHW39/Oc/t06fPm0VFhZyC3k7hDrOq1atshwOh/Xv//7v1kcffWQvly5d6qlTCAuhjvPncXdV+4U61lVVVVa/fv2sBQsWWGfOnLF2795txcfHWy+++GJPnUJYCHWcCwsLrX79+ln/9m//Zp09e9b6wx/+YN17773Wd77znZ46hbBw6dIl6/jx49bx48ctSdYvfvEL6/jx49b//u//WpZlWfn5+dasWbPs+tZbyBcvXmydPn3aWr9+PbeQ365++ctfWkOHDrUcDoc1adIk66233rK3ffWrX7Wys7OD6rdv327dd999lsPhsB544AGruLi4mzsOT6GM8913321JumEpLCzs/sbDTKh/nq9HyAlNqGN95MgRKy0tzXI6ndY999xj/eQnP7GuXbvWzV2Hn1DG+erVq9by5cute++914qJibGSk5Ot73//+9Ynn3zS/Y2HkT/+8Y9t/pvbOrbZ2dnWV7/61Rv2GTdunOVwOKx77rnH+u1vf9ulPUZYFnNxAADAPFyTAwAAjETIAQAARiLkAAAAIxFyAACAkQg5AADASIQcAABgJEIOAAAwEiEHAAAYiZADAACMRMgBAABGIuQAAAAjEXIAAICR/h8oMEXpBOWrkwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(total_infos_2.values(), bins=np.linspace(0, 1, 50))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42dcbcc8",
   "metadata": {},
   "source": [
    "# prepare the 2nd hoot dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "326e1b84",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:54.739773Z",
     "start_time": "2024-06-22T04:03:54.127360Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "349901\n"
     ]
    }
   ],
   "source": [
    "high_cer_infos_2 = {}\n",
    "for k, v in total_infos_2.items():\n",
    "    k_lang = metas_map[k][\"lang\"]\n",
    "    # should probably also play it safe\n",
    "    cut_threshold = min(langs_cer_cut.get(k_lang, 0.5), 0.6)\n",
    "    if v <= cut_threshold:\n",
    "        high_cer_infos_2[k] = v\n",
    "print(len(high_cer_infos_2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "636c3311",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:55.201970Z",
     "start_time": "2024-06-22T04:03:54.741253Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "245162 1915.328125\n"
     ]
    }
   ],
   "source": [
    "high_cer_train_info_2 = []\n",
    "for info in train_info:\n",
    "    if (\n",
    "        info[\"id\"] in high_cer_infos_2 and info[\"duration\"] < 240\n",
    "    ):  # --> this is how v3 t9 data is prepared\n",
    "        # if info[\"id\"] in high_cer_infos_2 and 210 < info[\"duration\"] < 300:\n",
    "        high_cer_train_info_2.append(info)\n",
    "print(len(high_cer_train_info_2), len(high_cer_train_info_2) / 2 / 8 / 8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "bf451a42",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:55.718872Z",
     "start_time": "2024-06-22T04:03:55.203212Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total duration khr 13.30586861111111 60 239 26 4870\n",
      "Counter({'en': 140352, 'es': 44714, 'pt': 14153, 'fr': 6222, 'ko': 5266, 'de': 4308, 'ru': 3595, 'tr': 3305, 'ja': 2983, 'it': 2426, 'zh': 2118, 'ar': 1923, 'id': 1567, 'pl': 1379, 'sr': 972, 'he': 948, 'hu': 835, 'nl': 817, 'fi': 692, 'uk': 668, 'ro': 606, 'tl': 599, 'cs': 577, 'sv': 551, 'da': 405, 'hr': 395, 'fa': 336, 'bg': 279, 'ca': 221, 'sk': 195, 'no': 150, 'vi': 143, 'lv': 113, 'lt': 109, 'sq': 108, 'az': 101, 'uz': 96, 'af': 94, 'et': 90, 'sl': 85, 'eu': 73, 'sw': 55, 'ms': 51, 'hi': 49, 'arz': 41, 'sh': 31, 'th': 29, 'eo': 20, 'mk': 19, 'cy': 19, 'la': 18, 'pa': 17, 'ku': 16, 'nn': 15, 'als': 14, 'gl': 13, 'bs': 13, 'ceb': 12, 'be': 12, 'war': 10, 'ta': 10, 'jbo': 8, 'jv': 8, 'su': 8, 'is': 7, 'el': 7, 'ht': 6, 'nap': 6, 'br': 5, 'qu': 5, 'hy': 5, 'mg': 4, 'ast': 4, 'tk': 4, 'ckb': 3, 'mt': 3, 'ne': 3, 'ur': 3, 'ga': 3, 'io': 3, 'yi': 3, 'fy': 2, 'mzn': 2, 'gn': 2, 'km': 2, 'oc': 2, 'ilo': 2, 'ia': 1, 'am': 1, 'as': 1, 'so': 1, 'vec': 1, 'ie': 1, 'nah': 1, 'pms': 1, 'kn': 1, 'mr': 1, 'pam': 1, 'bn': 1, 'te': 1, 'si': 1, 'ml': 1, 'nds': 1, 'mn': 1, 'kw': 1, 'an': 1})\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    \"total duration khr\",\n",
    "    sum(m[\"duration\"] for m in high_cer_train_info_2) / 3600000,\n",
    "    min(m[\"duration\"] for m in high_cer_train_info_2),\n",
    "    max(m[\"duration\"] for m in high_cer_train_info_2),\n",
    "    min(len(m[\"text\"]) for m in high_cer_train_info_2),\n",
    "    max(len(m[\"text\"]) for m in high_cer_train_info_2),\n",
    ")\n",
    "print(Counter(m[\"lang\"] for m in high_cer_train_info_2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "90466614",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:55.810960Z",
     "start_time": "2024-06-22T04:03:55.720250Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "243162 2000\n"
     ]
    }
   ],
   "source": [
    "cutoff = -2000\n",
    "random.shuffle(high_cer_train_info_2)\n",
    "high_cer_train_info_2, high_cer_test_info_2 = (\n",
    "    high_cer_train_info_2[:cutoff],\n",
    "    high_cer_train_info_2[cutoff:],\n",
    ")\n",
    "print(len(high_cer_train_info_2), len(high_cer_test_info_2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "90b9e528",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:55.813818Z",
     "start_time": "2024-06-22T04:03:55.812052Z"
    }
   },
   "outputs": [],
   "source": [
    "# high_cer_train_info_2[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "74ef0ed9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:04:03.543564Z",
     "start_time": "2024-06-22T04:03:56.320394Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/v4_cer_50_long_train_ytm.json\", \"w\") as fp:\n",
    "#     for l in high_cer_train_info_2:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')\n",
    "# with open(\"/home/tony/Data/Hoot/v4_cer_50_long_test_ytm.json\", \"w\") as fp:\n",
    "#     for l in high_cer_test_info_2:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "61409fbd",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:04:03.547199Z",
     "start_time": "2024-06-22T04:04:03.544875Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Done\n"
     ]
    }
   ],
   "source": [
    "print(\"Done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "535130a0",
   "metadata": {},
   "source": [
    "# Curate a seperate list of long audios, for just evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "13fa3abf",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:56.027320Z",
     "start_time": "2024-06-22T04:03:55.951668Z"
    }
   },
   "outputs": [],
   "source": [
    "# high_cer_train_info_2_long = []\n",
    "# for info in train_info:\n",
    "#     if info[\"id\"] in high_cer_infos_2 and 240 < info[\"duration\"] < 300 :\n",
    "#         high_cer_train_info_2_long.append(info)\n",
    "# print(len(high_cer_train_info_2_long))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "5c7f0742",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:56.097806Z",
     "start_time": "2024-06-22T04:03:56.028838Z"
    }
   },
   "outputs": [],
   "source": [
    "# random.shuffle(high_cer_train_info_2_long)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "01e7ad2b",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:56.166249Z",
     "start_time": "2024-06-22T04:03:56.098738Z"
    }
   },
   "outputs": [],
   "source": [
    "# selected_validation_set = []\n",
    "# max_lang_s = {\"en\": 500}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "cfbf0a99",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:56.244508Z",
     "start_time": "2024-06-22T04:03:56.167208Z"
    }
   },
   "outputs": [],
   "source": [
    "# c = Counter()\n",
    "# for m in high_cer_train_info_2_long:\n",
    "#     c[m[\"lang\"]] += 1\n",
    "#     if c[m[\"lang\"]] < max_lang_s.get(m[\"lang\"], 50):\n",
    "#         selected_validation_set.append(m)\n",
    "# print(len(selected_validation_set))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "f8d88911",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-06-22T04:03:56.317784Z",
     "start_time": "2024-06-22T04:03:56.245561Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/v3_validation_set.json\", \"w\") as fp:\n",
    "#     for l in selected_validation_set:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1e7ac97",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
