{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "bf70f34f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import re\n",
    "import json\n",
    "import tqdm\n",
    "import uuid\n",
    "import funcy\n",
    "import numpy as np\n",
    "from suno_utils.audio import Audio, Token, Tokens\n",
    "from suno_utils.utils.numbers import safe_round\n",
    "from suno_utils.utils.text import normalize_whitespace, write_jsonl\n",
    "from suno_utils.web.harvest import get_file_ext, get_filename\n",
    "\n",
    "RAW_BASE_DIR = \"/mnt/data-ssd-1/data/private/customer/speechly/gcp_bucket/\"\n",
    "RAW_AUDIO_DIRS = [\n",
    "    os.path.join(RAW_BASE_DIR, \"spotify/audios\"),\n",
    "]\n",
    "\n",
    "BASE_DIR = \"/mnt/data-ssd-1/data/private/customer/speechly/2022-11-17_spotify-10h\"\n",
    "\n",
    "AUDIO_DIR = os.path.join(BASE_DIR, \"audio\")\n",
    "TO_REV_DIR = os.path.join(BASE_DIR, \"to_rev\")\n",
    "TO_REV_AUDIO_DIR = os.path.join(TO_REV_DIR, \"audio\")\n",
    "FROM_REV_DIR = os.path.join(BASE_DIR, \"from_rev\")\n",
    "\n",
    "SEGMENT_DATE_DIR = \"2022_11_17\"\n",
    "SEGMENTS_DIR = os.path.join(BASE_DIR, \"pipeline\", SEGMENT_DATE_DIR, \"segments\")\n",
    "ARTIFACTS_DIR = os.path.join(BASE_DIR, \"pipeline\", SEGMENT_DATE_DIR, \"artifacts\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "c769f21a",
   "metadata": {},
   "outputs": [],
   "source": [
    "os.makedirs(AUDIO_DIR, exist_ok=True)\n",
    "os.makedirs(TO_REV_DIR, exist_ok=True)\n",
    "os.makedirs(TO_REV_AUDIO_DIR, exist_ok=True)\n",
    "os.makedirs(FROM_REV_DIR, exist_ok=True)\n",
    "os.makedirs(SEGMENTS_DIR, exist_ok=True)\n",
    "os.makedirs(ARTIFACTS_DIR, exist_ok=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c3cd79ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "GLOBAL_HOTWORDS = []"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3bf11bab",
   "metadata": {},
   "source": [
    "## Prepare rev data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "965eb6c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "SAMPLE_RATE = 16_000\n",
    "EXPECTED_FILE_TYPE = \"wav\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "9ff97b1c",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 298/298 [00:00<00:00, 506.65it/s]\n"
     ]
    }
   ],
   "source": [
    "# save in dir with known sample rate as wavs and keep track of id\n",
    "filepaths_info = []\n",
    "for raw_audio_dir in RAW_AUDIO_DIRS:\n",
    "    for fn in tqdm.tqdm(os.listdir(raw_audio_dir)):\n",
    "        if get_file_ext(fn) != EXPECTED_FILE_TYPE:\n",
    "            print(\"found unknown file:\", fn)\n",
    "            continue\n",
    "        uid = str(uuid.uuid4())\n",
    "        from_fp = os.path.join(raw_audio_dir, fn)\n",
    "        to_fp = os.path.join(AUDIO_DIR, f\"{uid}.wav\")\n",
    "        Audio.from_file(from_fp, sample_rate=SAMPLE_RATE, byte_width=2).to_wav(to_fp)\n",
    "        filepaths_info.append((uid, from_fp, to_fp))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "deb0bebc",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(BASE_DIR, \"raw_data_manifest.json\"), \"w\") as f:\n",
    "    json.dump(filepaths_info, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "4da818da",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "46.9 mins of audio (1.2% overhead)\n",
      "44.9 mins of audio (1.2% overhead)\n"
     ]
    }
   ],
   "source": [
    "MIN_REV_FILE_DURATION_S = 45 * 60\n",
    "INDICATOR_AUDIO_DIR = \"/mnt/data-ssd-1/data/custom/segment_indicators\"\n",
    "SILENCE_DURATION_S = 0.25\n",
    "\n",
    "audio_rev_metas = []\n",
    "tmp_segments_audio = []\n",
    "tmp_segments_meta = []\n",
    "tmp_n = 0\n",
    "for n_step, (uid, _, filepath) in enumerate(filepaths_info):\n",
    "    # add indicator\n",
    "    indicator_str = str(tmp_n).zfill(3)\n",
    "    tmp_indicator_audios = []\n",
    "    for c in indicator_str:\n",
    "        tmp_indicator_audios.append(\n",
    "            Audio.from_file(\n",
    "                os.path.join(INDICATOR_AUDIO_DIR, f\"{c}_fast.wav\"), \n",
    "                sample_rate=SAMPLE_RATE, \n",
    "                byte_width=2,\n",
    "            )\n",
    "        )\n",
    "    indicator_audio = Audio.concatenate(tmp_indicator_audios)\n",
    "    tmp_segments_audio.append(indicator_audio)\n",
    "    tmp_segments_meta.append({\n",
    "        \"segment_number\": tmp_n,\n",
    "        \"type\": \"indicator\",\n",
    "        \"duration_s\": indicator_audio.duration_s,\n",
    "        \"indicator_str\": indicator_str,\n",
    "    })\n",
    "    # add silence\n",
    "    if SILENCE_DURATION_S > 0:\n",
    "        silence_audio = Audio.from_array(\n",
    "            np.zeros(int(SAMPLE_RATE * SILENCE_DURATION_S), dtype=np.int16), SAMPLE_RATE\n",
    "        )\n",
    "        tmp_segments_audio.append(silence_audio)\n",
    "        tmp_segments_meta.append({\n",
    "            \"segment_number\": tmp_n,\n",
    "            \"type\": \"silence\",\n",
    "            \"duration_s\": SILENCE_DURATION_S,\n",
    "        })\n",
    "    # add audio\n",
    "    audio = Audio.from_file(filepath, sample_rate=SAMPLE_RATE, byte_width=2)\n",
    "#     audio = remove_music(audio, wet=1.0, model_name=\"mdx_extra_q\")\n",
    "    tmp_segments_audio.append(audio)\n",
    "    tmp_segments_meta.append({\n",
    "        \"segment_number\": tmp_n,\n",
    "        \"type\": \"speech\",\n",
    "        \"duration_s\": audio.duration_s,\n",
    "        \"orginial_audio_offset_s\": 0,\n",
    "        \"orginial_audio_uid\": uid,\n",
    "    })\n",
    "    # add silence\n",
    "    if SILENCE_DURATION_S > 0:\n",
    "        silence_audio = Audio.from_array(\n",
    "            np.zeros(int(SAMPLE_RATE * SILENCE_DURATION_S), dtype=np.int16), SAMPLE_RATE\n",
    "        )\n",
    "        tmp_segments_audio.append(silence_audio)\n",
    "        tmp_segments_meta.append({\n",
    "            \"segment_number\": tmp_n,\n",
    "            \"type\": \"silence\",\n",
    "            \"duration_s\": SILENCE_DURATION_S,\n",
    "        })\n",
    "    # prep for next step and decide if we make new file\n",
    "    tmp_n += 1\n",
    "    running_duration_s = np.sum([e[\"duration_s\"] for e in tmp_segments_meta])\n",
    "    if (\n",
    "        (running_duration_s >= MIN_REV_FILE_DURATION_S) or \n",
    "        (n_step == len(filepaths_info) - 1 and running_duration_s > 0)\n",
    "    ):\n",
    "        audio_rev = Audio.concatenate(tmp_segments_audio)\n",
    "        running_speech_duration_s = np.sum([e[\"duration_s\"] for e in tmp_segments_meta if e[\"type\"] == \"speech\"])\n",
    "        print(\"{} mins of audio ({}% overhead)\".format(\n",
    "            round(running_duration_s / 60, 1),\n",
    "            round((1 - running_speech_duration_s / running_duration_s) * 100, 1)\n",
    "        )) \n",
    "        uid = str(uuid.uuid4())\n",
    "        rev_audio_filepath = os.path.join(TO_REV_AUDIO_DIR, f\"{uid}.mp3\")\n",
    "        audio_rev.to_mp3(rev_audio_filepath)\n",
    "        audio_rev_metas.append({\n",
    "            \"uid\": uid,\n",
    "            \"audio_filepath\": rev_audio_filepath,\n",
    "            \"segments_meta\": tmp_segments_meta,\n",
    "            \"duration_s\": audio_rev.duration_s,\n",
    "        })\n",
    "        tmp_segments_audio = []\n",
    "        tmp_segments_meta = []\n",
    "        tmp_n = 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "4d16d48e",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(TO_REV_DIR, f\"audio_rev_metas.json\"), \"w\") as f:\n",
    "    json.dump(audio_rev_metas, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a453909d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "5fc18307",
   "metadata": {},
   "source": [
    "## (optional) investigate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "dc409c9d",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(TO_REV_DIR, f\"audio_rev_metas.json\")) as f:\n",
    "    audio_rev_metas = json.load(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "ea85a5f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# with open(os.path.join(RAW_DATA_DIR, \"transcripts.tsv\")) as f:\n",
    "#     transcripts = [e.split(\"\\t\") for e in f.read().strip().split(\"\\n\")]\n",
    "# assert(all([len(e) == 2 for e in transcripts]))\n",
    "# transcripts = [(uid, text.lower()) for uid, text in transcripts]\n",
    "# print(len(transcripts), \"transcripts\")\n",
    "# transcripts[:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8dbf534b",
   "metadata": {},
   "outputs": [],
   "source": [
    "Audio.play_audio(Audio.from_file(audio_rev_metas[0][\"audio_filepath\"]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40f5c4a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "Audio.play_audio(Audio.from_file(audio_rev_metas[-1][\"audio_filepath\"]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "58a2ca6f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41e4dbe5",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "426ba2c3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dfc212cd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "88a9e9cc",
   "metadata": {},
   "source": [
    "## Send stuff to rev"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "05fbe672",
   "metadata": {},
   "outputs": [],
   "source": [
    "from suno_utils.web.rev import get_auth_string, upload_file, make_order, make_cc_order\n",
    "\n",
    "with open(\"/home/georg/.secrets/secrets.json\") as f:\n",
    "    secrets = json.load(f)\n",
    "    \n",
    "CLIENT_API_KEY = secrets[\"REV_CLIENT_API_KEY\"]\n",
    "USER_API_KEY = secrets[\"REV_USER_API_KEY\"]\n",
    "AUTH_STR = get_auth_string(CLIENT_API_KEY, USER_API_KEY)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2db71de1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10.1 hours total\n"
     ]
    }
   ],
   "source": [
    "with open(os.path.join(TO_REV_DIR, f\"audio_rev_metas.json\")) as f:\n",
    "    audio_rev_metas = json.load(f)\n",
    "\n",
    "ORDER_REF_STR = \"sl_sf_10h\"\n",
    "\n",
    "tot_duration_s = np.sum([m[\"duration_s\"] for m in audio_rev_metas])\n",
    "print(round(tot_duration_s / 60 / 60, 1), \"hours total\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "8c66f7f9",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 13/13 [01:16<00:00,  5.87s/it]\n"
     ]
    }
   ],
   "source": [
    "order_items = []\n",
    "for m in tqdm.tqdm(audio_rev_metas):\n",
    "    media_loc = upload_file(AUTH_STR, m[\"audio_filepath\"], file_ref_str=m[\"uid\"])\n",
    "    order_items.append(\n",
    "        {\n",
    "            \"media_loc\": media_loc,\n",
    "            \"hotwords\": GLOBAL_HOTWORDS,\n",
    "            \"duration_s\": int(np.ceil(m[\"duration_s\"])),\n",
    "            \"uuid\": m[\"uid\"],\n",
    "        }\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a0ee5f4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(TO_REV_DIR, \"01_order_items.json\"), \"w\") as f:\n",
    "    json.dump(order_items, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8318e46f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# order_number = make_order(AUTH_STR, order_items, order_ref_str=ORDER_REF_STR)\n",
    "order_number = make_cc_order(AUTH_STR, order_items, order_ref_str=ORDER_REF_STR)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "27549d51",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(TO_REV_DIR, \"02_order_numer.txt\"), \"w\") as f:\n",
    "    f.write(order_number)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0096715b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "576b2bef",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "b33dc8e0",
   "metadata": {},
   "source": [
    "## Get rev stuff"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e8b59ece",
   "metadata": {},
   "outputs": [],
   "source": [
    "from suno_utils.web.rev import get_auth_string, get_finished_order, get_transcript\n",
    "\n",
    "with open(\"/home/georg/.secrets/secrets.json\") as f:\n",
    "    secrets = json.load(f)\n",
    "    \n",
    "CLIENT_API_KEY = secrets[\"REV_CLIENT_API_KEY\"]\n",
    "USER_API_KEY = secrets[\"REV_USER_API_KEY\"]\n",
    "AUTH_STR = get_auth_string(CLIENT_API_KEY, USER_API_KEY)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "9e4e40af",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(TO_REV_DIR, \"02_order_numer.txt\")) as f:\n",
    "    order_number = f.read()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d2a371b5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# # grab while still in progress\n",
    "# from suno_utils.web.rev import _get_order_details, _parse_order_response\n",
    "# order_details = _get_order_details(AUTH_STR, order_number)\n",
    "# _, transcript_metas = _parse_order_response(order_details)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "9275ae0d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# grab all of it\n",
    "transcript_metas = get_finished_order(AUTH_STR, order_number, blocking=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "df28d887",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:01<00:00, 12.96it/s]\n"
     ]
    }
   ],
   "source": [
    "# 27 total\n",
    "for transcript_meta in tqdm.tqdm(transcript_metas):\n",
    "    transcript_filepath = os.path.join(FROM_REV_DIR, transcript_meta[\"uuid\"] + \".srt\")\n",
    "    if os.path.exists(transcript_filepath):\n",
    "        continue\n",
    "    transcript_subrip = get_transcript(AUTH_STR, transcript_meta)\n",
    "    with open(transcript_filepath, \"w\") as f:\n",
    "        f.write(transcript_subrip)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed8a84c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# !rm /mnt/data-ssd-1/data/private/customer/speechly/2022-11-17_spotify-10h/from_rev/4eb00cc1-e75a-4992-930b-4ea333b5688e.srt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef35045b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c0c1c29c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "b15ce9de",
   "metadata": {},
   "source": [
    "## Parsing rev subrips"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2b80ff9a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import string\n",
    "from nltk.corpus import words as nltk_words\n",
    "from suno_utils.utils.numbers import safe_round\n",
    "from suno_utils.audio.data_model import Token, Tokens, TEXT, TAG\n",
    "from suno_utils.customers.sanas.pipeline import get_segments\n",
    "from suno_utils.utils.text import normalize_whitespace\n",
    "\n",
    "COMMON_EN_WORDS = set(nltk_words.words())\n",
    "\n",
    "def _parse_srt(transcript_srt):\n",
    "    blocks = []\n",
    "    for block in transcript_srt.strip().split(\"\\n\\n\"):\n",
    "        lines = block.strip().split(\"\\n\")\n",
    "        segment_nr = int(lines[0])\n",
    "        start_str, end_str = lines[1].split(\" --> \")\n",
    "        h, m, s = start_str.split(\":\")\n",
    "        start_s = int(h) * 60**2 + int(m) * 60 + float(s.replace(\",\", \".\"))\n",
    "        h, m, s = end_str.split(\":\")\n",
    "        end_s = int(h) * 60**2 + int(m) * 60 + float(s.replace(\",\", \".\"))\n",
    "        text_lines = lines[2:]\n",
    "        blocks.append({\n",
    "            \"segment_nr\": segment_nr, \n",
    "            \"offset_s\": safe_round(start_s),\n",
    "            \"duration_s\": safe_round(end_s - start_s),\n",
    "            \"text_lines\": text_lines, \n",
    "        })\n",
    "    if blocks[0][\"segment_nr\"] != 1:\n",
    "        raise ValueError(\"First block doesn't start with 1.\")\n",
    "    if any(np.diff([e[\"segment_nr\"] for e in blocks]) != 1):\n",
    "        raise ValueError(\"Parsed block numbers are not consecutive.\")\n",
    "    return blocks\n",
    "\n",
    "def _tag_repl(m):\n",
    "    s = m.group()\n",
    "    if s is not None:\n",
    "        s = s.lower()\n",
    "        s = re.sub(r\"[\\(\\)]\", \" \", s.lower())\n",
    "        s = normalize_whitespace(s)\n",
    "        s = s.replace(\" \", \"_\")\n",
    "        return f\" [{s}] \"\n",
    "\n",
    "def _partial_word_repl(m):\n",
    "    s = m.group()\n",
    "    word = s.strip(\".- \")\n",
    "    probably_fragment = word not in COMMON_EN_WORDS\n",
    "    if probably_fragment:\n",
    "        return f\"{word}* -- \"\n",
    "    else:\n",
    "        return f\"{word} -- \"\n",
    "\n",
    "from suno_utils.utils.text import make_unique_list\n",
    "\n",
    "def _desetify_meta_repl(m):\n",
    "    s = m.group()\n",
    "    tags = re.findall(r\"\\[.*?\\]\", s)\n",
    "    tags = make_unique_list(tags)\n",
    "    return \" {} \".format(\" \".join(tags))\n",
    "    \n",
    "ALLOWED_TAGS = set([\n",
    "    \"laughter\", \"foreign_language\", \"inaudible\", \"music\", \"redacted\", \"crosstalk\", \"beep\"\n",
    "])\n",
    "\n",
    "def _standardize_tags(text):\n",
    "    # collapse meta tags and filter\n",
    "    for m in list(re.finditer(r\"\\[.*?\\]\", text))[::-1]:\n",
    "        tag_text = text[m.start() + 1:m.end() - 1]\n",
    "        # collapse notation\n",
    "        if \"foreign\" in tag_text:\n",
    "            tag_text = \"foreign_language\"\n",
    "        if \"laugh\" in tag_text:\n",
    "            tag_text = \"laughter\"\n",
    "        if \"indistinct\" in tag_text or \"mumbl\" in tag_text:\n",
    "            tag_text = \"inaudible\"\n",
    "        if \"music\" in tag_text or \"\\\"\" in tag_text or \"plays\" in tag_text or \"sing\" in tag_text:\n",
    "            tag_text = \"music\"\n",
    "        if \"chatter\" in tag_text:\n",
    "            tag_text = \"crosstalk\"\n",
    "        # filter\n",
    "        if tag_text in ALLOWED_TAGS:\n",
    "            cleaned_tag_text = f\"[{tag_text}]\"\n",
    "        else:\n",
    "            cleaned_tag_text = \"\"\n",
    "        text = text[:m.start()] + cleaned_tag_text + text[m.end():]\n",
    "    return text\n",
    "    \n",
    "# speechly style choices\n",
    "repeat_ptn = r\"\"\n",
    "for a, b in zip(string.ascii_uppercase, string.ascii_lowercase):\n",
    "    repeat_ptn += r\"[\" + a + b + r\"]\" + b + \"{2,}|\"\n",
    "repeat_ptn = repeat_ptn[:-1]\n",
    "\n",
    "def _repeat_repl(m):\n",
    "    return m.group()[:2]\n",
    "\n",
    "def _consolidate_style_choices(text):\n",
    "    # 'cause -> cause\n",
    "    text = text.replace(\"'em\", \"em\")\n",
    "    text = text.replace(\"'Til\", \"Til\")\n",
    "    text = text.replace(\"'til\", \"til\")\n",
    "    text = text.replace(\"'Till\", \"Til\")\n",
    "    text = text.replace(\"'till\", \"til\")\n",
    "    text = text.replace(\"'Cause\", \"Cause\")\n",
    "    text = text.replace(\"'cause\", \"cause\")\n",
    "    text = text.replace(\"'Bout\", \"Bout\")\n",
    "    text = text.replace(\"'bout\", \"bout\")\n",
    "    text = text.replace(\"'round\", \"round\")\n",
    "    text = text.replace(\"'neath\", \"neath\")\n",
    "    text = text.replace(\"'member\", \"member\")\n",
    "    text = text.replace(\"Imma\", \"I'ma\")\n",
    "    text = text.replace(\"imma\", \"i'ma\")\n",
    "    # fittin', flippin' -> ing\n",
    "    text = re.sub(r\"in\\'(?=\\s|$)\", \"ing\", text)\n",
    "    # word repl\n",
    "    text = re.sub(r\"\\b([Bb])ruh\\b\", \"\\\\1ro\", text)\n",
    "    text = re.sub(r\"\\b([Yy])up\\b\", \"\\\\1ep\", text)\n",
    "    text = re.sub(r\"\\b([Cc])uz\\b\", \"\\\\1ause\", text)\n",
    "    # Mmm, ooooh\n",
    "    text = re.sub(repeat_ptn, _repeat_repl, text)\n",
    "    text = re.sub(r\"\\b([Oo])oh\\b\", \"\\\\1h\", text)\n",
    "    text = re.sub(r\"\\b([Uu])uh\\b\", \"\\\\1h\", text)\n",
    "    text = re.sub(r\"\\b([Aa])ah\\b\", \"\\\\1h\", text)\n",
    "    return text\n",
    "    \n",
    "def parse_rev_captions(transcript_srt, lang=\"en\"):\n",
    "    if lang != \"en\":\n",
    "        raise NotImplementedError(\"only en is supported for now.\")\n",
    "    if len(re.findall(r\"\\(beep\\)\", transcript_srt)) >= 3:\n",
    "        print(\"careful, lots of (beep) detected\")\n",
    "    cur_speaker_id = 0\n",
    "    token_list = []\n",
    "    for block in _parse_srt(transcript_srt):\n",
    "        lines = block[\"text_lines\"]\n",
    "        if len(lines) == 0:\n",
    "            continue\n",
    "        # handle music lyrics\n",
    "        annotated_lines = []\n",
    "        cur_lyrics = False\n",
    "        for line in lines:\n",
    "            is_start = re.match(r\"^\\s*♪.*\", line)\n",
    "            is_end = re.match(r\".*♪\\s*$\", line)\n",
    "            if is_start:\n",
    "                line = line.strip()[1:]\n",
    "            if is_end:\n",
    "                line = line.strip()[:-1]\n",
    "            if is_start and is_end:\n",
    "                annotated_lines.append((line, True))\n",
    "                cur_lyrics = False\n",
    "            elif is_start:\n",
    "                annotated_lines.append((line, True))\n",
    "                cur_lyrics = True\n",
    "            elif is_end:\n",
    "                annotated_lines.append((line, True))\n",
    "                cur_lyrics = False\n",
    "            else:\n",
    "                annotated_lines.append((line, False))\n",
    "            if re.match(r\".*♪\\s*$\", line):\n",
    "                cur_lyrics = False\n",
    "        # merge if no lyrics and if no new speaker\n",
    "        if all([not is_lyrics for _, is_lyrics in annotated_lines]):\n",
    "            merged_lines = []\n",
    "            tmp_lines = []\n",
    "            for line, _ in annotated_lines:\n",
    "                if re.search(r\"^\\s*\\-\", line):\n",
    "                    if len(tmp_lines) > 0:\n",
    "                        merged_lines.append((\" \".join([s.strip() for s in tmp_lines]), False))\n",
    "                        tmp_lines = []\n",
    "                tmp_lines.append(line)\n",
    "            if len(tmp_lines) > 0:\n",
    "                merged_lines.append((\" \".join([s.strip() for s in tmp_lines]), False))\n",
    "                tmp_lines = []\n",
    "        else:\n",
    "            merged_lines = annotated_lines[:]\n",
    "        # add actual lines\n",
    "        for raw_line, is_lyrics in merged_lines:\n",
    "            # handle speaker change\n",
    "            line = raw_line.strip()\n",
    "            if line[:1] == \"-\":\n",
    "                cur_speaker_id += 1\n",
    "                line = line[1:].strip()\n",
    "            # handle meta tags\n",
    "            if re.search(r\"\\([^\\)]*\\(\", line):  # treat nested by brute forcing\n",
    "                line = re.sub(r\"\\((.*)\\)\", _tag_repl, line)\n",
    "            line = re.sub(r\"\\((.*?)\\)\", _tag_repl, line)\n",
    "            # handle redacted\n",
    "            line = re.sub(r\"[^\\s]*\\*+\", \" [redacted] \", line)\n",
    "            # handle hesitations and word fragments\n",
    "            line = re.sub(r\"\\s\\-[\\s\\-]*\", \" -- \", line)  # handle single dash\n",
    "            # TODO: this fails for eg. He said \"Yes-\".\n",
    "            line = re.sub(r\"[A-Za-z]+(\\.{2,}|\\-(\\s|$))\", _partial_word_repl, line)\n",
    "            line = re.sub(r\"\\.{2,}\", \" \", line)  # we only keep interruptions as --\n",
    "            # collapse meta tags and discard if necessary\n",
    "            line = _standardize_tags(line)\n",
    "            # discard partial tags (usually nested)\n",
    "            line = re.sub(r\"^[^\\[]{,20}\\]\", \"\", line)\n",
    "            # clean standalone punctuation (from behind tags)\n",
    "#             line = re.sub(r\"(\\[.*?\\])([\\.\\,\\!\\?\\s]+)\", \" \\\\2 \\\\1 \", line)  # swap with meta\n",
    "            line = re.sub(r\"\\][\\.\\,\\!\\?\\-\\s]+\", \"] \", line)  # remove if two consecutive metas\n",
    "            line = re.sub(r\"[\\.\\,\\!\\?\\-\\s]*\\s([\\.\\,\\!\\?])\", \"\\\\1\", line)\n",
    "            line = re.sub(r\"(^|\\s+)[\\.\\,\\?\\!\\-\\s]+\", \" \", line)\n",
    "            # specific style choices\n",
    "            line = _consolidate_style_choices(line)\n",
    "            # add tokens\n",
    "            line = normalize_whitespace(line)\n",
    "            if len(line) == 0:\n",
    "                continue\n",
    "            tokens = []\n",
    "            for s in line.split():\n",
    "                # identify word fragment\n",
    "                if re.match(r\"^[^\\*]+\\*$\", s):\n",
    "                    is_fragment = True\n",
    "                    s = s[:-1]\n",
    "                else:\n",
    "                    is_fragment = False\n",
    "                if s[:1] == \"[\" and s[-1:] == \"]\":\n",
    "                    is_text = False\n",
    "                elif s == \"--\":\n",
    "                    is_text = False\n",
    "                else:\n",
    "                    is_text = True\n",
    "                if is_text:\n",
    "                    token = Token(\n",
    "                        s, \n",
    "                        speaker_id=cur_speaker_id, \n",
    "                        type=TEXT, \n",
    "                        metadata={\"is_lyrics\": is_lyrics},\n",
    "                    )\n",
    "                else:\n",
    "                    token = Token(s, type=TAG)\n",
    "                if token.type == TAG and len(tokens) > 0 and token == tokens[-1]:\n",
    "                    # skip consecutive meta tokens\n",
    "                    continue\n",
    "                tokens.append(token)\n",
    "                if is_fragment:\n",
    "                     tokens.append(Token(\"[word_fragment_boundary]\", type=TAG))\n",
    "            token_list.extend(tokens)\n",
    "    # do things with global context\n",
    "    # de-setify metas\n",
    "    cleaned_tokens = []\n",
    "    tmp_tokens = []\n",
    "    for token in token_list:\n",
    "        if token.type != TAG:\n",
    "            if len(tmp_tokens) > 0:\n",
    "                cleaned_tokens.extend(tmp_tokens)\n",
    "                tmp_tokens = []\n",
    "            cleaned_tokens.append(token)\n",
    "        else:\n",
    "            if token.value not in set([t.value for t in tmp_tokens]):\n",
    "                tmp_tokens.append(token)\n",
    "    if len(tmp_tokens) > 0:\n",
    "        cleaned_tokens.extend(tmp_tokens)\n",
    "        tmp_tokens = []\n",
    "    transcript_tokens = Tokens(cleaned_tokens)\n",
    "    return transcript_tokens"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "00e04fcf",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(TO_REV_DIR, f\"audio_rev_metas.json\")) as f:\n",
    "    audio_rev_metas = json.load(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "936b45dd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "23/23 segments retained in 919bef11-56ec-4b1b-a230-3c4436c04858.\n",
      "23/23 segments retained in f8bd18e4-a765-4260-8c12-8f650720db7e.\n",
      "23/23 segments retained in ac2325ae-399a-4536-9026-111f8e8249fd.\n",
      "23/23 segments retained in a68d5a45-a626-49ff-9a45-1c23aedb3993.\n",
      "23/23 segments retained in ab5448d1-ced9-4b37-bcf8-84fd30ce3dad.\n",
      "23/23 segments retained in 4eb00cc1-e75a-4992-930b-4ea333b5688e.\n",
      "23/23 segments retained in 924e3bfb-5656-4154-98fb-8983b35254d3.\n",
      "23/23 segments retained in 9c9c30fa-3e28-4c3f-a8e1-93ab7e4f6d5a.\n",
      "23/23 segments retained in 8dcb6a53-75b6-4a82-9f42-caae0368fc98.\n",
      "23/23 segments retained in 1afd4dce-c167-4440-bd39-89ff406dd197.\n",
      "23/23 segments retained in ee835c7b-1d86-4d30-b2d8-5ab2c7180fdb.\n",
      "23/23 segments retained in 8424b49c-d3c7-4042-8ae2-677376f8bbbb.\n",
      "22/22 segments retained in 8aac2ce5-a72c-4299-8501-9a2546ae65cf.\n"
     ]
    }
   ],
   "source": [
    "# from suno_utils.web.rev import parse_transcript\n",
    "segment_transcripts = []\n",
    "for m in audio_rev_metas:#[3:4]:\n",
    "#     if m[\"uid\"] != \"59511101-f9fe-4fd8-aff4-69927a0ad3e4\":\n",
    "#         continue\n",
    "    srt_filepath = os.path.join(FROM_REV_DIR, m[\"uid\"] + \".srt\")\n",
    "    if not os.path.exists(srt_filepath):\n",
    "        print(\"not found, skipping...\")\n",
    "        continue\n",
    "    with open(srt_filepath) as f:\n",
    "        transcript_srt = f.read()\n",
    "    rev_transcript = parse_rev_captions(transcript_srt)\n",
    "    speech_segment_info = [mm for mm in m[\"segments_meta\"] if mm[\"type\"] == \"speech\"]\n",
    "    n_segments = len(speech_segment_info)\n",
    "    assert(len(speech_segment_info) == m[\"segments_meta\"][-1][\"segment_number\"] + 1)\n",
    "    token_segments = get_segments(rev_transcript, n_segments, global_indicator_speaker=False, n_indicator_digits=3)\n",
    "    segment_transcripts_chunk = []\n",
    "    missing_ids = set(range(n_segments))\n",
    "    for segment_idx, tokens in token_segments:\n",
    "        segment_info = speech_segment_info[segment_idx]\n",
    "        segment_transcripts_chunk.append({\n",
    "            \"uid\": segment_info[\"orginial_audio_uid\"],\n",
    "            \"duration_s\": segment_info[\"duration_s\"],\n",
    "            \"transcript\": tokens.anonymize_speakers(),\n",
    "        })\n",
    "        missing_ids -= set([segment_idx])\n",
    "    missing_ids = sorted([str(n) for n in missing_ids])\n",
    "    missing_str = \"\"\n",
    "    if len(missing_ids) > 0:\n",
    "        missing_str = \" (\" + \",\".join(missing_ids[:5])\n",
    "        if len(missing_ids) > 5:\n",
    "            missing_str += \"...\"\n",
    "        missing_str += \")\"\n",
    "    print(\"{}/{} segments retained in {}{}.\".format(\n",
    "        len(segment_transcripts_chunk), n_segments, m[\"uid\"], missing_str\n",
    "    ))\n",
    "    segment_transcripts.extend(segment_transcripts_chunk)\n",
    "#     break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "2cbe6494",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for m in segment_transcripts[:5]:\n",
    "#     print(m[\"uid\"])\n",
    "#     print(m[\"transcript\"].text)\n",
    "#     print(\"-\"*10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "136464c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# print(transcript_srt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "50313c41",
   "metadata": {},
   "outputs": [],
   "source": [
    "# segment_uid = \"d1bf2bea-0c9e-4223-9bb5-45ffa0acd428\"\n",
    "# for m in segments_manifest:\n",
    "#     if m[\"id\"] == segment_uid:\n",
    "#         print(\"transcript id:\", m[\"source_transcript_id\"])\n",
    "#         break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "90178e26",
   "metadata": {},
   "outputs": [],
   "source": [
    "# save as json\n",
    "import copy\n",
    "l = []\n",
    "for m in segment_transcripts:\n",
    "    e = copy.deepcopy(m)\n",
    "    e[\"transcript\"] = e[\"transcript\"].as_dict()\n",
    "    l.append(e)\n",
    "with open(os.path.join(BASE_DIR, \"parsed_transcripts.json\"), \"w\") as f:\n",
    "    json.dump(l, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4f02f420",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "703efe1d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9937474e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "2624f95e",
   "metadata": {},
   "source": [
    "## prepare pipeline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "9433c48a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# map segment id to rev submission id\n",
    "with open(os.path.join(TO_REV_DIR, f\"audio_rev_metas.json\")) as f:\n",
    "    audio_rev_metas = json.load(f)\n",
    "segment_to_rev_id = {}\n",
    "for m in audio_rev_metas:\n",
    "    rev_id = m[\"uid\"]\n",
    "    for mm in m[\"segments_meta\"]:\n",
    "        if mm[\"type\"] != \"speech\":\n",
    "            continue\n",
    "        segment_to_rev_id[mm[\"orginial_audio_uid\"]] = rev_id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "a29859c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(BASE_DIR, \"parsed_transcripts.json\")) as f:\n",
    "    segment_transcripts = json.load(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "020e71bb",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 298/298 [00:00<00:00, 141503.75it/s]\n"
     ]
    }
   ],
   "source": [
    "manifest = []\n",
    "for m in tqdm.tqdm(segment_transcripts):\n",
    "    segment_filepath = os.path.join(AUDIO_DIR, m[\"uid\"] + \".wav\")                          \n",
    "    new_segment_filepath = os.path.join(SEGMENTS_DIR, \"{}.wav\".format(m[\"uid\"]))\n",
    "    if not os.path.exists(new_segment_filepath):\n",
    "        audio = Audio.from_file(segment_filepath, sample_rate=16_000, byte_width=2)\n",
    "        audio.to_wav(new_segment_filepath)\n",
    "    manifest.append({\n",
    "        \"id\": m[\"uid\"],\n",
    "        \"uri\": new_segment_filepath,\n",
    "        \"duration_s\": m[\"duration_s\"],\n",
    "        \"transcript\": {\"tokens\": m[\"transcript\"]},\n",
    "        \"ignore_segment\": False,\n",
    "        \"ignore_reason\": \"\",\n",
    "        \"source_audio_offset_s\": 0,\n",
    "        \"source_audio_uri\": segment_filepath,\n",
    "        \"source_audio_id\": m[\"uid\"],\n",
    "        \"source_transcript_id\": segment_to_rev_id[m[\"uid\"]],\n",
    "        \"source_transcript_uri\": os.path.join(FROM_REV_DIR, segment_to_rev_id[m[\"uid\"]] + \".srt\"),\n",
    "    })"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "cee8873a",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(ARTIFACTS_DIR, \"01_segment_meta.json\"), \"w\") as f:\n",
    "    json.dump(manifest, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96c9e4f4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6cf2b71d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "651e980e",
   "metadata": {},
   "source": [
    "## QA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "a8dae9e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10.0 hours\n"
     ]
    }
   ],
   "source": [
    "with open(os.path.join(ARTIFACTS_DIR, \"01_segment_meta.json\")) as f:\n",
    "    segments_manifest = json.load(f)\n",
    "print(round(np.sum([e[\"duration_s\"] for e in segments_manifest]) / 60 / 60, 1), \"hours\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "ae6f9277",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: rev parse \"You-\"\n",
    "# TODO: mistake\n",
    "#   d1bf2bea-0c9e-4223-9bb5-45ffa0acd428\n",
    "#   John 3:20. I'm gonna read 1st John 3:18 through 20, cause I think that helps to understand this a little \n",
    "#   bit more. And here's what it says, little children [word_fragment_boundary] Zero, teo, zero. Episode page \n",
    "#   18 is four lines as the ending section of a paragraph on the previous page, and then there's a page break "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "6a5f0e8c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7893eb42-b246-412b-8c52-73dbed03c746\n",
      "Star game are the Jets the most interesting team in the NFL this off season plus can the Minnesota Vikings follow in Tampa Bay Buccaneers Footsteps? I'm Peter Makowski, starting your day with the stories you need to know and the biggest debates in sports you're locked on today. [music] Searching, call Major Force. Found him. Let's start with the biggest story. [music] We haven't heard much about the NBA All-Star game lately, which is likely headed to Atlanta in less than a month. What's going on with that? Maria Martin with our friends at 11 Alive Sports, gives us an update. An NBA All-Star game announced that It seemed eminent but his word circulated that the league was scrambling to put a game together. I Think it's stupid. Player criticism arose. Reports stated that the league and the players association liked the idea of having the game but the actual players, not so much. Still dealing with a with a pandemic. We're still deal dealing with everything that's been going on and we're gonna bring the whole league into one city that's open. Obviously you guys can see I'm not very happy about it. After LeBron's comments, no announcement, just murmurs of the league continuing to work out the details. The job for the union has been to try to make sure our players are healthy and safe. Chris Paul is the president of the NBA Players Association and advocated for an all-Star game and he's still working to make that happen. Different situations, you know guys who've been playing a lot of games who haven't really had much breaks, you know guys look at that break as an opportunity to see their families. Television rights are what makes it too appealing for the league to give up. Last year's game saw ratings increase of 8%, 7.3 million viewers ad sold out in record time in 2020, bringing in millions. We all know why we're playing it. You know, is money on the line just putting, putting money over health right now? There is no timeline for an announcement but it's likely coming. It may not bring the same fan for it.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/6f5e5265-9230-45d2-959c-79b6cf0a0b76.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "5b5fa4e1-f85b-4341-bb7b-8090511cf20a\n",
      "Out in the world now that you can land on, and I think they're a marketplace, I'm pretty sure. Oh! That's cool. Yeah. And another good thing that I think is useful, when you land on a Planet Now, it tells you what minerals are there, so you don't waste your time That smart. Yeah. Yeah. You know, cause we mined so much shit that we didn't need. Have I sounded so stupid, how the minerals were just big columns of shit, just herds coming up out the ground. You couldn't go You couldn't mine for them underground. Yeah. They were just on the surface of the plane. They were just there? Yeah. Imagine each planet, a solid ball, that you could not dig into, and that's what no man Skype. Oh! You mean like mass effect to mining thing? Sure. Did you guys know that? No. I never I hated the combat. I didn't finish it. Oh! It was either a giant nugget, or it was like a Washington Monument column of just whatever, aluminum, iron, or whatever. Did you have a gun? Yeah Yeah, you had a mining gun. It was a mining gun, and then you could switch it to do damage. Oh! Okay. Yeah, it was cool. I'm kind of looking forward to playing the update. Yeah, I'm gonna play it. I'm gonna play it. I wanna dust it off again. All right, I see that. Check it out. Oh! Yeah, right. Some people don't. I know, I see I wanna hear your review. I'm not gonna check it out either, Teacher. Your review is gonna be snore. It's gonna be bad. Maybe in the, I mean, other updates, they'll have where the language that you learn means more than just figuring out what other people are saying. That would be great, cause I loved finding the words, the word stones. I really enjoyed that too. That kind of gave it Oh! Like a siren? Mystical thing. I mean, you didn't get a power from it though. It just helped you understand the alien language. It was just so cool. It made that Could you then kill them? No, it was like a monument. No, you got to see a hologram sometimes, or it would tell you like a story. Oh! That's Or it would be a riddle sometimes. It's dumb. Whatever. Everyone else agrees with the Soft, he's a fucking nerd, not my guess, I will. [laughter] Okay, good. Thank God it's done.\" All right, sorry. Yeah. I could do it again. Get your DVDs game. I'm over\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/0f8151db-5164-4e82-b791-c3b47af82a2f.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "436425aa-eb41-4518-b000-cc5e159eb8f1\n",
      "Snap, and today we're gonna be talking about the meaning of Easter. So, stay tuned. [music] So, I'm gonna kick off this episode with the Bible verse John 3:16, which a lot of people know this by heart, but if you don't, \"It's for God so loved the world that he gave his only begotten son that whosoever believes in him shall not perish but have eternal life.\" So, Jesus died on the cross for our sins so that we could have eternal life in heaven. And this is huge because Easter weekend is about celebrating the resurrection of Jesus because he was beaten, crucified, spit on, probably cursed at and tortured like completely tortured and he died and was buried and then three days later he arose from the grave and ascended up to heaven. So, this is showing us that he conquered death and he also redeemed us from sin if we believe in him. So, I know I'm a sinner, I'll admit that I sin on a daily basis, whether it is complaining, lusting, saying things I shouldn't say, not trusting in God when I should be trusting in God. Like there's so many things, you name it, I've done it, we've all done it but with God, like he accepts us as who we are, he knows we're going to sin. But it's important for us to repent our sins so that we can have everlasting life in heaven. And I'm a big believer that if you try your best to do what's right and have Jesus Christ in your heart.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/be5ac274-08c7-410b-8e42-fba415b6ae8d.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "2f3e3ae2-dbfe-42dd-88df-7ca533811c65\n",
      "was your course. And now the one \"Parental Responsibilities,\" Ben's not here, unfortunately, he's got family responsibilities. But thankfully, we're joined by many other people. Matt, what are your responsibilities? Are they at you yourself misses at the stage? Yeah, but I'm also dog sitting this weekend, so my responsibilities grew by two pit bulls. So, I've got expanded responsibilities this week. Oh, shit. Yeah, big bun line. And what are the pit bulls' names? Bailey and Tucker. Bailey and Tucker? Those a pretty good pit bull names. I've heard pit bulls are actually very friendly dogs, and they get a bad rap. Yeah, these are absolute babies. They are adorable. I mean, when they bark they're terrifying. I'll think the heart, but that's the only time. Good. So that's good. So, I've responsibility. Oh no, I see. Well, the dogs are. I have a cat beyond obviously being a child, dogs are a lot more work. So I wish you the best of luck, and I know you might have to leave us as you're juggling girlfriend, possible responsibilities. So before that happens, maybe, how are you? Yeah, no, I'm, I'm well thanks. Managed to shirk most the responsibility, taking some early leave. So very much enjoying the fear, the freedom from most responsibility. What's it like? I've forgotten. I mean, it was a weekend, but knowing you can go without having to check on a Monday morning evening, it was a great feeling not having to open a laptop today. Yes. Yeah. And for those of you who are also African, when it comes to the 16th, which is a public holiday, the country generally shuts down after the 16th. Do you guys know why the 16th is a public holiday day? Fun fact. Sorry.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/8ed0c0a8-6378-47b7-978f-40af604df564.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "db1cde4b-7573-41c0-89a0-02b63228206c\n",
      "Cultivate your intuition so that you can let go of indecisiveness and really claim your yes and your no. [music] Welcome to the Cyclical podcast. I'm your host Cassandra Wilder and I'm a naturopathic doctor and the leading expert in women's cyclical health and menstruation. Let's get started. Hi beautiful friend. Welcome back to the podcast. Before I dive into all this juiciness around intuition and learning how to trust your gut, I want to invite you to a workshop I'm leading in just a couple days. Every once in a blue moon I get to lead an incredible free live workshop where hundreds, if not thousands of women join me live and we demystify periods, hormones, and I provide some epic value in a 60 minute workshop. The link is in the show notes right now to save your spot. It is held live on June 13th. So when I say run, don't walk, I literally mean it. So link in the show notes, save your spot right now. Pause this, go to the show notes, put your name and email in. That way you don't miss it. I've only opened up a thousand spots and I know these are gonna be gone within two or three days. So, I can't wait to see you there. These workshops are really special. The energy there is amazing and just seeing how many women are really devoted to supporting themselves and nourishing their health is astounding. If you're there live too, you'll also get first access and hundreds of dollars in bonuses for period reboot. So if that was already on your radar, yeah, you wanna be there. All right, well let's start talking about intuition, especially now that I'm sure your intuition is vibrating right now. Saying \"What? A free workshop, what period reboot?\" [laughter] But really that's how it works, friends. We are magnetized to the things we are meant to do. Intuition is such a beautiful subject. I did a podcast about intuition probably like two years ago. Friends, can you believe I've had this podcast for two and a half years? That's so wild. Some of you are OG.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/e4010e85-73b9-41ea-9d7d-e87a8eb6456e.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "# random ones\n",
    "# l = [e for e in segments_manifest if len(e[\"transcript\"][\"tokens\"]) == 0]\n",
    "l = segments_manifest[:]\n",
    "random.shuffle(l)\n",
    "for e in l[:5]:\n",
    "    print(e[\"id\"])\n",
    "    print(Tokens.from_dict(e[\"transcript\"][\"tokens\"]).text)\n",
    "    Audio.play_audio(e[\"uri\"])\n",
    "    print(\"-\"*10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "081a8b29",
   "metadata": {},
   "outputs": [],
   "source": [
    "# # get rev id for segment\n",
    "# segment_uid = \"846622bb-b4ab-439c-9316-3683831bafbe\"\n",
    "# for m in segments_manifest:\n",
    "#     if m[\"id\"] == segment_uid:\n",
    "#         print(m[\"source_transcript_id\"])\n",
    "#         break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a574e8b2",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "36eb7b98",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "7b8ddb47",
   "metadata": {},
   "source": [
    "## run pipeline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "id": "1e319351",
   "metadata": {},
   "outputs": [],
   "source": [
    "# # reset pipeline\n",
    "# !mv /mnt/data-ssd-1/data/private/customer/speechly/2022-11-17_spotify-10h/pipeline/2022_11_17/artifacts/01_segment_meta.json /tmp/01_segment_meta.json\n",
    "# !rm -rf /mnt/data-ssd-1/data/private/customer/speechly/2022-11-17_spotify-10h/pipeline/2022_11_17/artifacts/*\n",
    "# !mv /tmp/01_segment_meta.json /mnt/data-ssd-1/data/private/customer/speechly/2022-11-17_spotify-10h/pipeline/2022_11_17/artifacts/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "7fcf3139",
   "metadata": {},
   "outputs": [],
   "source": [
    "# # 17mins for 40h\n",
    "# CUDA_VISIBLE_DEVICES=\"\" python /home/georg/notebooks/customers/speechly/spotify/run_modified_pipeline.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7abcae45",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "245bf746",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b01ea31f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "0a83b4f7",
   "metadata": {},
   "source": [
    "## Check difficult norm stuff"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "id": "a1c4d36f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# from suno_utils.utils.text_normalizer import normalize, NORMALIZER, _normalize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0e5a473a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# $68,500\n",
    "# $68,500\n",
    "# $73,745 \n",
    "# $59,395\n",
    "# $1,800 eighteen hundred\n",
    "# 7,800 pounds seventy eight hundred pounds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "id": "646395d1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# NORMALIZER.normalize(\n",
    "#     text=\"$1,800\",\n",
    "#     verbose=False,\n",
    "#     n_tagged=-1,\n",
    "#     punct_post_process=False,\n",
    "# )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "id": "66508929",
   "metadata": {},
   "outputs": [],
   "source": [
    "# CUSTOM_NORM_RULES = [\n",
    "#     (re.compile(r\"\\$\"), \" \"),\n",
    "#     (re.compile(r\"\\b([0-9])\\,([0-9])00\\b\"), \"\\\\1\\\\2 hundred\"),\n",
    "#     (re.compile(r\"\\$([0-9])\\,([0-9])00\\b\"), \"\\\\1\\\\2 hundred\"),\n",
    "# ]\n",
    "\n",
    "# _normalize(\n",
    "#     text_list=\"$1,800\",\n",
    "#     asr_prediction=\"eighteen hundred\",\n",
    "#     custom_norm_rules=CUSTOM_NORM_RULES,\n",
    "# )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "066dea18",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb1aec05",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "cfa1946d",
   "metadata": {},
   "source": [
    "## look at results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "30275498",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10.0 hours\n"
     ]
    }
   ],
   "source": [
    "with open(os.path.join(ARTIFACTS_DIR, \"02_segment_meta_post_norm_and_asr.json\")) as f:\n",
    "    segments_manifest = json.load(f)\n",
    "print(round(np.sum([e[\"duration_s\"] for e in segments_manifest]) / 60 / 60, 1), \"hours\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "5848265d",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dbb240ec-7db0-46cc-a368-9c78d6ef970c\n",
      "Laying out that Danielle Hunter saga. So I'm trying to figure out how best to go about this because Vikings fans I think already know about the news that came out today being Monday the 14th. So we will get to that. But let's start off with the Danielle Hunter saga. That is more of a tongue twister than I thought it would be. And let's go back to the beginning, which we will define as being Vikings training camp last season. So last season, at some point during Vikings training camp, it started to become, reporters I guess, were becoming aware that Danielle Hunter was not practicing. And what they were told is that he had a minor tweak and it seemed like the Vikings were playing it off as though they were expecting Danielle Hunter to come back. And part of why it seemed like they were thinking that is because the Vikings during training camp, or at least within that period between training camp and the start of the season, signed another defensive end, Yannick Ngakoue. And it seemed like they were planning on pairing Ngakoue with Danielle Hunter going into the season. But slowly as we got closer and closer to the start of the season, we became more and more aware that the Danielle Hunter injury was more than just a tweak. And what was revealed was that Danielle Hunter actually had a neck injury that ended up requiring season ending surgery. So it turned out that in Ngakoue did not end up being paired with Danielle Hunter. And even though he only played six games for the Vikings last season, ended up leading the Vikings in sacks. So it is fair to say that having Danieli Hunter not on the field for the Vikings last year was incredibly detrimental to their defensive success. So with that in mind, the goal became, or the view, I guess the hope for the future became that Danielle Hunter would be able to make a full recovery and be able to come back in the 2021 season. However, during sometime in the middle, towards the end of October, if I'm remembering correctly, a couple of reporters gave a little bit of fire\n",
      "laying out that danielle hunter saga so i'm trying to figure out how best to go about this because vikings fans i think already know about the news that came out today being monday the fourteenth so we will get to that but let's start off with the danielle hunter saga that is more of a tongue twister than i thought it would be and let's go back to the beginning which we will define as being vikings training camp last season so last season at some point during vikings training camp it started to become reporters i guess were becoming aware that danielle hunter was not practicing and what they were told is that he had a minor tweak and it seemed like the vikings were playing it off as though they were expecting danielle hunter to come back and part of why it seemed like they were thinking that is because the vikings during training camp or at least within that period between training camp and the start of the season signed another defensive end yannick ngakoue and it seemed like they were planning on pairing ngakoue with danielle hunter going into the season but slowly as we got closer and closer to the start of the season we became more and more aware that the danielle hunter injury was more than just a tweak and what was revealed was that danielle hunter actually had a neck injury that ended up requiring season ending surgery so it turned out that in ngakoue did not end up being paired with danielle hunter and even though he only played six games for the vikings last season ended up leading the vikings in sacks so it is fair to say that having danieli hunter not on the field for the vikings last year was incredibly detrimental to their defensive success so with that in mind the goal became or the view i guess the hope for the future became that danielle hunter would be able to make a full recovery and be able to come back in the twenty twenty one season however during sometime in the middle towards the end of october if i'm remembering correctly a couple of reporters gave a little bit of fire\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/1a206ca4-9bbd-46ad-ab46-f49f761068ee.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "dc86a5c1-94c2-4c23-9664-8b6f801120f2\n",
      "[inaudible] through 2012. It's a pretty long case. It's a, it's a, it's an odd case, the suspected suicide / murder. It's like they don't know, well they know who did it now obviously, but they didn't know who did it then. So, the case of Pamela Shelley, she was age 32 when she died and she was shot in her home by, it was suspected that she committed suicide in her bathroom of her home with her kids in the house. They were about to leave Arkansas where they lived with Pamela's boyfriend Ronnie. And it was, they were about to move out. They were, they had their packed up stuff in the car. They were literally minutes away from leaving. And Ronnie, her boyfriend at the time said he was claim to be outside of their house and he heard a gunshot and he ran in and saw Pam lying on the floor with a gun in her hand and said that she had just committed suicide. And so after, like hours after when the paramedics arrived, when the police arrived, Ronnie's family started saying that Pam had been suicidal for a really long time. That her family had a history of suicide, that her sister committed suicide and said that she had been very depressed because her daughter wasn't happy and saying that she really wanted to leave Arkansas because she wanted her dad, her no, she wanted to leave Texas, which is where they lived. And she wanted to leave Texas and move back to Arkansas with her ex-husband. Jessie's hugs. She said that Kayla who was 12 at the time, really didn't like living in Texas. So she was told that she, she was told, you know, air quote.\n",
      "[inaudible] through two thousand twelve it's a pretty long case it's a it's a it's an odd case the suspected suicide murder it's like they don't know well they know who did it now obviously but they didn't know who did it then so the case of pamela shelley she was age thirty two when she died and she was shot in her home by it was suspected that she committed suicide in her bathroom of her home with her kids in the house they were about to leave arkansas where they lived with pamela's boyfriend ronnie and it was they were about to move out they were they had their packed up stuff in the car they were literally minutes away from leaving and ronnie her boyfriend at the time said he was claim to be outside of their house and he heard a gunshot and he ran in and saw pam lying on the floor with a gun in her hand and said that she had just committed suicide and so after like hours after when the paramedics arrived when the police arrived ronnie's family started saying that pam had been suicidal for a really long time that her family had a history of suicide that her sister committed suicide and said that she had been very depressed because her daughter wasn't happy and saying that she really wanted to leave arkansas because she wanted her dad her no she wanted to leave texas which is where they lived and she wanted to leave texas and move back to arkansas with her ex husband jessie's hugs she said that kayla who was twelve at the time really didn't like living in texas so she was told that she she was told you know air quote\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/91a40ce2-9be7-4459-bbf0-7342aae9eabe.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "f2388506-46f0-4cd5-a15c-8d41205f3c13\n",
      "Find the opportunity to be among the living. Glory be to God in the highest, for waking us up with a new strength, waking us up with joy, waking us up with Christ, waking up Waking us up with the special ability. Every part of our body's function way. Glory be to God in the highest, who kept us safe from the evils of the night, arrows of the night. Glory be to God, who deliver us from workers of inequity, from the many corporations and plans, that have taken place in the night. They were all averted. And so we don't know what has happened, because the whole of heaven was by our side. They fought and they won, and future belonged to the almighty God, while the blessing is ours, and that's why we are part of the living. If you are one of those who can hear this podcast this morning, you are so privileged, you are so privileged. It is because you're alive. If you think it's your alarm that wake you up this morning, you will have to put that same alarm, behind or besides a dead body, and see whether the alarm ring, the dead body will be able to stand up. It is God and not your alarm. It is because you are alive, that the alarm rang, and you are able to hear that it's ringing, and you are able to stand up. So glory be to God in the highest for He has done, for what He's doing, and for what He's still going to do. I celebrate you almighty God. I celebrate His gratefulness, His merciness, His goodness, His protection, for what He has been doing, for what He has done, for what He has [word_fragment_boundary] For what He's still going to do. I praise the holy name. It is good to praise God, because\n",
      "find the opportunity to be among the living glory be to god in the highest for waking us up with a new strength waking us up with joy waking us up with christ waking up waking us up with the special ability every part of our body's function way glory be to god in the highest who kept us safe from the evils of the night arrows of the night glory be to god who deliver us from workers of inequity from the many corporations and plans that have taken place in the night they were all averted and so we don't know what has happened because the whole of heaven was by our side they fought and they won and future belonged to the almighty god while the blessing is ours and that's why we are part of the living if you are one of those who can hear this podcast this morning you are so privileged you are so privileged it is because you're alive if you think it's your alarm that wake you up this morning you will have to put that same alarm behind or besides a dead body and see whether the alarm ring the dead body will be able to stand up it is god and not your alarm it is because you are alive that the alarm rang and you are able to hear that it's ringing and you are able to stand up so glory be to god in the highest for he has done for what he's doing and for what he's still going to do i celebrate you almighty god i celebrate his gratefulness his merciness his goodness his protection for what he has been doing for what he has done for what he has [word_fragment_boundary] for what he's still going to do i praise the holy name it is good to praise god because\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/a7f5ba38-ce5c-423a-9c5c-e625ec6cdc62.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "5b39c5d9-edbc-405d-ad35-351fdabe6d37\n",
      "Completely hairless, completely hairless or completely covered in hair. Hey. Okay, that means no mustache, Steve, nothing. Oh Jesus. That could be a complete disaster. Did you call in the Lord on that one? Yes, I did on that one and I don't. Or how completely hair would you have to be? No body hair, no hair. No, I mean, but how would you, when you say completely hair, how would you be? You mean covered in hair? Yeah. Like as in caveman hair? Yeah, I think. Werewolf? Werewolf hair. Yeah, all of the above. You just talking about what I got now. Like Sister Deidra at the church she got hair. Mustache, beard, Hair in your ears, in your nose, between your eyes. Are you talking about no eyebrows. No brows, no nothing. No, I'm going take that hair, I'm gonna shape it up. Cause that hairless you fitting to look like just a damn blob. You fitting to look like an emoji. Taking all that back now? Hey, I'm not fitting to be no walking around like no damn emoji now. That ain't what I'm fitting to do. I ain't got no eyebrows. None, uh-uh. No mustache though. No dawg, I got problems with no eyebrows. Paint em on, lot of women draw em on. I know, but it's shocking when you get up on it and you discover that it's a drawing that it is artwork. [laughter] You could get em tattooed on. It's artwork. Yeah, you can get that done too. But you gotta do something else. I just don't like to discover that it's artwork that you have none. All right. All right, moving on. Would you rather sweat profusely in the bedroom or just have insatiable dry mouth? Just would you rather sweat a lot in the bedroom or just would you like to have a dry mouth all time? Yeah in the bedrrom. No, I'm gonna take the sweat.\n",
      "completely hairless completely hairless or completely covered in hair hey okay that means no mustache steve nothing oh jesus that could be a complete disaster did you call in the lord on that one yes i did on that one and i don't or how completely hair would you have to be no body hair no hair no i mean but how would you when you say completely hair how would you be you mean covered in hair yeah like as in caveman hair yeah i think werewolf werewolf hair yeah all of the above you just talking about what i got now like sister deidra at the church she got hair mustache beard hair in your ears in your nose between your eyes are you talking about no eyebrows no brows no nothing no i'm going take that hair i'm gonna shape it up cause that hairless you fitting to look like just a damn blob you fitting to look like an emoji taking all that back now hey i'm not fitting to be no walking around like no damn emoji now that ain't what i'm fitting to do i ain't got no eyebrows none uh uh no mustache though no dawg i got problems with no eyebrows paint em on lot of women draw em on i know but it's shocking when you get up on it and you discover that it's a drawing that it is artwork [laughter] you could get em tattooed on it's artwork yeah you can get that done too but you gotta do something else i just don't like to discover that it's artwork that you have none all right all right moving on would you rather sweat profusely in the bedroom or just have insatiable dry mouth just would you rather sweat a lot in the bedroom or just would you like to have a dry mouth all time yeah in the bedrrom no i'm gonna take the sweat\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/7555d5b9-b9ec-42f8-92ea-5f83a313adc7.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "d097cbb5-0ce3-4dff-86a4-b4ad013303be\n",
      "I go to get all of my Breckenridge Brewery as often as possible. I'm Rudo, he's AJ Hayfley. On today's episode, obviously, the news of the day is Jason Botterill has been fired by the Buffalo Sabres as their GM. I believe they also fired his assistant GM as well. I feel sorry for that guy. Yeah. Their executive vice president is now the GM of the team, Kevin Adams. Anyway, that's not the point, the point is, Buffalo continues to struggle with a cycle of trouble at the GM position. Not quite getting it right, feeling like they're living the perpetual rebuild of Groundhogs Day at this point. And we can start there, and eventually the point of this, is to work it back into the abes, and how they might be able to take advantage of it. Yeah, I mean, we'll get there at some point. But for right now, it was just interesting to see that they made this decision. You can't You can't blame Botterill for not trying. He did a lot of things in his years there. It's not like he's been there a really long time. He's made upwards of 20 trades. He's spent money, he's gotten rid of some bad money. He's done He certainly did things. He's tried to do a lot of stuff there. If we were If you were to pull up exactly what he's done for them, it's a long list of things that, some of it is confusing, like, Marcos Candela was a great example of how I think they have bigger problems than just talent, because Marcos Candela was super reliable for years in Minnesota.\n",
      "i go to get all of my breckenridge brewery as often as possible i'm rudo he's a j hayfley on today's episode obviously the news of the day is jason botterill has been fired by the buffalo sabres as their g m i believe they also fired his assistant g m as well i feel sorry for that guy yeah their executive vice president is now the g m of the team kevin adams anyway that's not the point the point is buffalo continues to struggle with a cycle of trouble at the g m position not quite getting it right feeling like they're living the perpetual rebuild of groundhogs day at this point and we can start there and eventually the point of this is to work it back into the abes and how they might be able to take advantage of it yeah i mean we'll get there at some point but for right now it was just interesting to see that they made this decision you can't you can't blame botterill for not trying he did a lot of things in his years there it's not like he's been there a really long time he's made upwards of twenty trades he's spent money he's gotten rid of some bad money he's done he certainly did things he's tried to do a lot of stuff there if we were if you were to pull up exactly what he's done for them it's a long list of things that some of it is confusing like marcos candela was a great example of how i think they have bigger problems than just talent because marcos candela was super reliable for years in minnesota\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/120030a5-96a5-4356-b2ff-5ae42b5c3974.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "# random ones\n",
    "# l = [e for e in segments_manifest if len(e[\"transcript\"][\"tokens\"]) == 0]\n",
    "l = segments_manifest[:]\n",
    "random.shuffle(l)\n",
    "for e in l[:5]:\n",
    "    print(e[\"id\"])\n",
    "    print(Tokens.from_dict(e[\"transcript\"][\"tokens\"]).text)\n",
    "    print(Tokens.from_dict(e[\"transcript_normalized\"][\"tokens\"]).text)\n",
    "    Audio.play_audio(e[\"uri\"])\n",
    "    print(\"-\"*10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "dab452cf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "d4c6e442-01eb-4a6e-a401-767e25ea544b\n",
      "Section of the podcast. So have a lot of good feedback from a lot of people who liked the Monday message last week. So I'm gonna continue with that for as long as I can. If I keep getting positive feedback. Again, these are all things that I look back on at the end of the week, on a Sunday or a Saturday or whatever day I decided to do this and look back into my notes or my journals that I've, gone through this week or I look ahead at what's to come and see what is going to be the most relevant thing to talk about, the most relevant topic, or something that really stuck out to me in the past week or over the past month, or something that I'm just eager to share with you guys. So today, January 18th, in honor of the great Dr. Martin Luther King Jr., we are talking about moving forward. And more specifically, you have to keep moving forward when difficult things cross your path or obstacles get in your way or you're faced with hardships, you have to keep moving forward. So this quote by MLK that I wanna share with you all today that I'm gonna be thinking about today and moving forward into 2021 as we all look to continue to strive for greatness, for success, to achieve our goals, whatever that may be. And the quote is: If you can't fly then run; if you can't run, then walk; if you can't walk, then crawl, but whatever you do, you have to keep moving forward.\" And I think this is extremely relevant because there's a lot of things going on in the world right now, but I'm not a political podcast. I'm not an overly political guy, so I'm not gonna go into that. But there are some crazy things going on in the world and there's always gonna be a reason, there's always gonna be an excuse to stop or to take a step back.\n",
      "section of the podcast so have a lot of good feedback from a lot of people who liked the monday message last week so i'm gonna continue with that for as long as i can if i keep getting positive feedback again these are all things that i look back on at the end of the week on a sunday or a saturday or whatever day i decided to do this and look back into my notes or my journals that i've gone through this week or i look ahead at what's to come and see what is going to be the most relevant thing to talk about the most relevant topic or something that really stuck out to me in the past week or over the past month or something that i'm just eager to share with you guys so today january eighteenth in honor of the great dr martin luther king jr we are talking about moving forward and more specifically you have to keep moving forward when difficult things cross your path or obstacles get in your way or you're faced with hardships you have to keep moving forward so this quote by m l k that i wanna share with you all today that i'm gonna be thinking about today and moving forward into twenty twenty one as we all look to continue to strive for greatness for success to achieve our goals whatever that may be and the quote is if you can't fly then run if you can't run then walk if you can't walk then crawl but whatever you do you have to keep moving forward and i think this is extremely relevant because there's a lot of things going on in the world right now but i'm not a political podcast i'm not an overly political guy so i'm not gonna go into that but there are some crazy things going on in the world and there's always gonna be a reason there's always gonna be an excuse to stop or to take a step back\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/4e1d1292-47ab-4b79-9d00-12a0ff5ddd31.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "2e648c58-09c7-4f81-a326-7a87c30ae5d2\n",
      "That's right, when they make the claims, we show up so you don't have to. I'm Ross Blocher. And I'm Carrie Poppy, and we are back at the Wim Hof seminar. Woohoo. All before the whole COVID situation started. Correct. We've been waiting to tell you about it cause we thought it would be fun for our MaxFunDrive. [music] MaxFunDrive. So, we'll tell you a bit more about the Iceman in just a moment, and us trying his methods, but we're still in the middle of MaxFunDrive here. Oh boy, Oh boy. Plenty of time to support us. Yeah, this is only week two of four. Yeah and the numbers are very encouraging. Yes. Thank you to all of you who have subscribed or upgraded. And, guess what? There's a new option now you can boost. Boost. your membership. So, we talk about the $5 membership, and that's where you get all of the bonus content. We've talked about the $10 membership, we've got a lot more to say about that, $20 and so forth. But, you can also, now this is new in this MaxFunDrive, if you're at, say, the $10 per month and you're just not ready to quite go to $20, you can choose an intermediate amount, and make that your monthly donation, and that will count as an upgraded membership. I wonder if you can do not full dollars, like if you can give, like, $5.69? [laughter] Yeah, an additional [music] 69. Yeah. Add pi to whatever it is you're currently at. [music] or like 69. Oh, oh I get it. Okay. Like a sexual thing. [laughter] Carrie just needed me to acknowledge the 69 in the room. Yeah, so that's an available option to you now. And we're really grateful because MaxFun members keep this going. You've kept us going through this very bizarre time, and we're super grateful for everybody who's already a member. And that's why we're doing our drive right now, to remind you that you're the reason we can make this content for you to enjoy. MaxFun is audience-supported, which means we are free to make the content\n",
      "that's right when they make the claims we show up so you don't have to i'm ross blocher and i'm carrie poppy and we are back at the wim hof seminar woohoo all before the whole covid situation started correct we've been waiting to tell you about it cause we thought it would be fun for our maxfundrive [music] maxfundrive so we'll tell you a bit more about the iceman in just a moment and us trying his methods but we're still in the middle of maxfundrive here oh boy oh boy plenty of time to support us yeah this is only week two of four yeah and the numbers are very encouraging yes thank you to all of you who have subscribed or upgraded and guess what there's a new option now you can boost boost your membership so we talk about the five dollars membership and that's where you get all of the bonus content we've talked about the ten dollars membership we've got a lot more to say about that dollar twenty and so forth but you can also now this is new in this maxfundrive if you're at say the ten dollars per month and you're just not ready to quite go to dollar twenty you can choose an intermediate amount and make that your monthly donation and that will count as an upgraded membership i wonder if you can do not full dollars like if you can give like five six nine [laughter] yeah an additional [music] six nine yeah add pi to whatever it is you're currently at [music] or like sixty nine oh oh i get it okay like a sexual thing [laughter] carrie just needed me to acknowledge the sixty nine in the room yeah so that's an available option to you now and we're really grateful because maxfun members keep this going you've kept us going through this very bizarre time and we're super grateful for everybody who's already a member and that's why we're doing our drive right now to remind you that you're the reason we can make this content for you to enjoy maxfun is audience supported which means we are free to make the content\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/09344ba0-7510-4302-9231-ae3cea042f4e.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "2eff3fef-31d2-40b6-bca4-3b0f43cdeed8\n",
      "Life, advocating for justice and gender issues. She has joined us online today to discuss insights from her book, Scars Across Humanity: Understanding and Overcoming Violence Against Women. Welcome Elaine, it's great to have you with us. Thank you, it's really good to be with you. Thank you, so Elaine, what inspired you to write a book about the different forms of violence women experience across the globe? Well, my interest in violence against Women started when I was quite a young woman and the editor of a Prissy woman's magazine put out a questionnaire asking if people had experienced any form of abuse, violence, or kind of intimate partner on these, they were invited to fill in the questionnaire. She was amazed at the response she got. And we were good friends and she, there was the days before internet. So she bundled it all in a big brown paper envelope and sent it to me. And when I read these as sponsors, I was a young wife myself, my early twenties, I was absolutely flabbergasted that this was going on right under our nose and we knew nothing at all about it. I was very naive. And I think that was my first experience of what it was like for many people, many women out there. And then bit by bit, the picture widened as I became involved in an incest counseling group and heard another set of stories. And then the big jump came when I was president of Tearfund. I became president of Tearfund in the 1990s, I started visiting many different countries and it was the same kinda pattern to same kind of message over and over again, but in many different cultural forms. And that's what threw me at first. But I realized this is the same product. It is violence abuse against women, but taking the cultural form that seemed appropriate in that particular country or culture. So for example, in India.\n",
      "life advocating for justice and gender issues she has joined us online today to discuss insights from her book scars across humanity understanding and overcoming violence against women welcome elaine it's great to have you with us thank you it's really good to be with you thank you so elaine what inspired you to write a book about the different forms of violence women experience across the globe well my interest in violence against women started when i was quite a young woman and the editor of a prissy woman's magazine put out a questionnaire asking if people had experienced any form of abuse violence or kind of intimate partner on these they were invited to fill in the questionnaire she was amazed at the response she got and we were good friends and she there was the days before internet so she bundled it all in a big brown paper envelope and sent it to me and when i read these as sponsors i was a young wife myself my early twenties i was absolutely flabbergasted that this was going on right under our nose and we knew nothing at all about it i was very naive and i think that was my first experience of what it was like for many people many women out there and then bit by bit the picture widened as i became involved in an incest counseling group and heard another set of stories and then the big jump came when i was president of tearfund i became president of tearfund in the nineteen nineties i started visiting many different countries and it was the same kinda pattern to same kind of message over and over again but in many different cultural forms and that's what threw me at first but i realized this is the same product it is violence abuse against women but taking the cultural form that seemed appropriate in that particular country or culture so for example in india\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/dbd642ab-bc5b-4b47-a3fc-a593b6114749.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "a6d13545-dbd7-46a4-98b7-a6854b8861f4\n",
      "Written by Zach Dean. What is up everyone? Welcome back to the show. This is Anthony, This is James. We're doing the Tomorrow war, which was just released on Amazon Prime. And this movie is sick. And like my expectations of it were like, eh, I guess I'll check it out. Maybe the trailer was was kind of enticing, but you couldn't really see what it was really about. Yeah, I remember seeing the trailer, and I was like, that looks okay, but I mean, it didn't catch my fancy too much. I was like, maybe I'll check it out if it gets good reviews. And then, but what I realized was the trailer was that way because it didn't give anything away. It only showed like the setup of the entire movie, and all the good stuff is left in the movie, and we're in the dark when you walk into this movie. And when I saw this film, I watched it alone with the lights off, and blasted the sound candles burning candles burning, the cat sleeping on the floor, and I was just blown away. This is like heart-pounding action, intense sequences. Super fun, really funny in themes like family and stuff. I feel like this movie was made by fans of big blockbuster movies. Yeah I mean the reviews are pretty bad, and it's rotten on Rotten Tomatoes, except for the audience scores, like 81% last time I checked. But I think it's in the fifties on Rotten Tomatoes. A lot of reviews are really mean, and like attacking it. And I think, you know, a lot of people attack Chris Pratt's movies outside of the Marvel franchise, because of his personal beliefs, which is ridiculous. That shouldn't have to factor into reviewing a movie or not. And I think this movie is so goddamn fun. I think it's my favorite movie of the year so far. Obviously, like Dunes is gonna probably surpass that for me, but it won't be as fun as this one. But my God, it was a blast. And the crazy thing is, it takes 45, 47 minutes for us to finally see the aliens. They just keep it hidden for so freaking long. And it's amazing. And the opening of the movie just like really entices you with him like dropping in, it looks like a Fortnight drop in into the map, [laughter] and he just falls into that pool. You're like, what the hell is going on? And I love\n",
      "written by zach dean what is up everyone welcome back to the show this is anthony this is james we're doing the tomorrow war which was just released on amazon prime and this movie is sick and like my expectations of it were like eh i guess i'll check it out maybe the trailer was was kind of enticing but you couldn't really see what it was really about yeah i remember seeing the trailer and i was like that looks okay but i mean it didn't catch my fancy too much i was like maybe i'll check it out if it gets good reviews and then but what i realized was the trailer was that way because it didn't give anything away it only showed like the setup of the entire movie and all the good stuff is left in the movie and we're in the dark when you walk into this movie and when i saw this film i watched it alone with the lights off and blasted the sound candles burning candles burning the cat sleeping on the floor and i was just blown away this is like heart pounding action intense sequences super fun really funny in themes like family and stuff i feel like this movie was made by fans of big blockbuster movies yeah i mean the reviews are pretty bad and it's rotten on rotten tomatoes except for the audience scores like eighty one percent last time i checked but i think it's in the fifties on rotten tomatoes a lot of reviews are really mean and like attacking it and i think you know a lot of people attack chris pratt's movies outside of the marvel franchise because of his personal beliefs which is ridiculous that shouldn't have to factor into reviewing a movie or not and i think this movie is so goddamn fun i think it's my favorite movie of the year so far obviously like dunes is gonna probably surpass that for me but it won't be as fun as this one but my god it was a blast and the crazy thing is it takes forty five forty seven minutes for us to finally see the aliens they just keep it hidden for so freaking long and it's amazing and the opening of the movie just like really entices you with him like dropping in it looks like a fortnight drop in into the map [laughter] and he just falls into that pool you're like what the hell is going on and i love\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/f8110817-2ba4-4914-af13-a95653e4e4bb.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "ffc3b919-d82d-43b9-9b9d-9fa4fee7c648\n",
      "I'm your host, Jordan D'Nelle, physician assistant, women's sexual health educator and intimacy coach. On today's episode, we are talking about some other non-hormonal forms of contraceptives. We are talking all about the fertile window, and the most popular form of birth control, worldwide sterilization. This is the fourth episode in our discussion on contraceptives. Before we get started, I am super excited to announce a project I've been working on. I am now offering intimacy coaching calls. To snag your free 20 minute call to help improve your intimacy, go to intimacy.vaginasvulvasandvibrators.com. I cannot wait to connect with you. All right, so today we are covering a couple different non-hormonal birth control options. Sterilization, abstinence, and natural family planning, which is also known as the fertility awareness method. In our prior couple of episodes, we have covered hormonal birth control options, as well as different barrier methods. My goal is that you get an idea of what's available and out there, to help you make the best decision that is right for you with your body. So let's jump right into it. The number one way to prevent pregnancy is to avoid intercourse and abstain. This method is up to 100% effective when done correctly. Now, the reality is this is a great theory, but for many people, this option is not realistic. And abstaining from intercourse is not something that they are interested in. But it is a form of birth control and should always be considered as an option and something for you to think about when making your decision about what is best for you. So the next non-hormonal option that we are gonna talk about\n",
      "i'm your host jordan d'nelle physician assistant women's sexual health educator and intimacy coach on today's episode we are talking about some other non hormonal forms of contraceptives we are talking all about the fertile window and the most popular form of birth control worldwide sterilization this is the fourth episode in our discussion on contraceptives before we get started i am super excited to announce a project i've been working on i am now offering intimacy coaching calls to snag your free twenty minute call to help improve your intimacy go to intimacy vaginasvulvasandvibrators dot com i cannot wait to connect with you all right so today we are covering a couple different non hormonal birth control options sterilization abstinence and natural family planning which is also known as the fertility awareness method in our prior couple of episodes we have covered hormonal birth control options as well as different barrier methods my goal is that you get an idea of what's available and out there to help you make the best decision that is right for you with your body so let's jump right into it the number one way to prevent pregnancy is to avoid intercourse and abstain this method is up to one hundred percent effective when done correctly now the reality is this is a great theory but for many people this option is not realistic and abstaining from intercourse is not something that they are interested in but it is a form of birth control and should always be considered as an option and something for you to think about when making your decision about what is best for you so the next non hormonal option that we are gonna talk about\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/f68b01b0-2846-4e92-a595-db991f3e49ca.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "# random ones\n",
    "# l = [e for e in segments_manifest if len(e[\"transcript\"][\"tokens\"]) == 0]\n",
    "l = segments_manifest[:]\n",
    "random.shuffle(l)\n",
    "n = 0\n",
    "for e in l:\n",
    "    text = Tokens.from_dict(e[\"transcript\"][\"tokens\"]).text\n",
    "    if not any((\n",
    "        re.search(r\"[0-9][^\\s0-9\\,\\.][^0-9]\", text),\n",
    "        re.search(r\"[^0-9][^\\s0-9\\,\\.][0-9]\", text),\n",
    "    )):\n",
    "        continue\n",
    "    print(e[\"id\"])\n",
    "    print(text)\n",
    "    print(Tokens.from_dict(e[\"transcript_normalized\"][\"tokens\"]).text)\n",
    "    Audio.play_audio(e[\"uri\"])\n",
    "    print(\"-\"*10)\n",
    "    n += 1\n",
    "    if n >= 5:\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "34165d5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# uid = \"6643b5a8-06de-45cb-a99f-351c54d49133\"\n",
    "# for e in segments_manifest:\n",
    "#     if e[\"id\"] == uid:\n",
    "#         print(\"full:\", Tokens.from_dict(e[\"transcript\"][\"tokens\"]).text)\n",
    "#         print(\"norm:\", Tokens.from_dict(e[\"transcript_normalized\"][\"tokens\"]).text)\n",
    "#         print(\"asr :\", e[\"transcript_asr\"][\"transcript\"])\n",
    "#         Audio.from_file(e[\"uri\"]).play()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "afd18433",
   "metadata": {},
   "outputs": [],
   "source": [
    "# l = []\n",
    "# for e in segments_manifest:\n",
    "#     l.extend(re.findall(r\"[a-zA-Z]+\\-[a-zA-Z]+\", Tokens.from_dict(e[\"transcript\"][\"tokens\"]).text))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "51e32035",
   "metadata": {},
   "outputs": [],
   "source": [
    "# # segment_uid = \"30815903-8a47-4d14-8557-41c352526d5d\"\n",
    "# # segment_uid = \"974c5846-5ae1-4521-9ca2-83175d563c55\"\n",
    "# # segment_uid = \"45a812db-16ef-494f-acde-6d151d012a70\"\n",
    "# segment_uid = \"383220cb-e8f1-4b6d-b39b-2d126eb50163\" \n",
    "\n",
    "# for n, m in enumerate(audio_rev_metas):\n",
    "#     rev_id = m[\"uid\"]\n",
    "#     for nn, mm in enumerate(m[\"segments_meta\"]):\n",
    "#         if mm[\"type\"] != \"speech\":\n",
    "#             continue\n",
    "#         if mm[\"orginial_audio_uid\"] == segment_uid:\n",
    "#             print(n, nn)\n",
    "#             print(audio_rev_metas[n][\"uid\"])\n",
    "#             print(audio_rev_metas[n][\"segments_meta\"][nn])\n",
    "# #             print(Tokens.from_dict(e[\"transcript\"][\"tokens\"]).text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "539144e1",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc0d9e56",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "938c2793",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "6b0192cb",
   "metadata": {},
   "source": [
    "## format output for speechly styleguide"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "798221f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: do we need to keep dashes during norm? what about M-mhm uh-huh, ..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "290b5f06",
   "metadata": {},
   "outputs": [],
   "source": [
    "from suno_utils.web.harvest import get_filename\n",
    "\n",
    "with open(os.path.join(BASE_DIR, \"raw_data_manifest.json\")) as f:\n",
    "    filepaths_info = json.load(f)\n",
    "id_to_original_id_map = {e[0]: get_filename(e[2], keep_extension=True) for e in filepaths_info}\n",
    "inv_id_to_original_id_map = {v: k for k, v in id_to_original_id_map.items()}\n",
    "\n",
    "with open(os.path.join(ARTIFACTS_DIR, \"02_segment_meta_post_norm_and_asr.json\")) as f:\n",
    "    segments_manifest = json.load(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "ecd8a4d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "def _convert_full_transcript(tokens):\n",
    "    transcript_l = []\n",
    "    for turn in tokens.speaker_turns:\n",
    "        turn_tokens = Tokens.from_dict(turn[\"tokens\"])\n",
    "        active_lyrics = False\n",
    "        text_l = []\n",
    "        for t in turn_tokens:\n",
    "            is_lyrics = False\n",
    "            if t.metadata is not None:\n",
    "                is_lyrics = t.metadata[\"is_lyrics\"]\n",
    "            if is_lyrics and not active_lyrics:\n",
    "                text_l.append(\"<lyrics>\")\n",
    "            if not is_lyrics and active_lyrics:\n",
    "                text_l.append(\"</lyrics>\")\n",
    "            text_l.append(t.value)\n",
    "            active_lyrics = is_lyrics\n",
    "        if active_lyrics:\n",
    "            text_l.append(\"</lyrics>\")\n",
    "        text = \" \".join(text_l)\n",
    "        text = re.sub(r\"\\<lyrics\\>\\s+\", \"<lyrics>\", text)\n",
    "        text = re.sub(r\"\\s+\\<\\/lyrics\\>\", \"</lyrics>\", text)\n",
    "        transcript_l.append(text)\n",
    "    transcript = \" [speaker_change] \".join(transcript_l)\n",
    "    transcript = re.sub(r\"\\s+\\[word\\_fragment\\_boundary\\]\", \"*\", transcript)\n",
    "    # fix some basic parse mistackes\n",
    "    transcript = re.sub(r\"^\\s*\\[music\\] \\[speaker\\_change\\]\\s*\", \"[music] \", transcript)\n",
    "    transcript = re.sub(r\"\\b([Ff])cuk\\b\", \"\\\\1uck\", transcript)\n",
    "    transcript = normalize_whitespace(transcript)\n",
    "    return transcript\n",
    "\n",
    "def _convert_norm_transcript(tokens):\n",
    "    transcript = tokens.text\n",
    "    transcript = transcript.replace(\" [word_fragment_boundary]\", \"*\")\n",
    "    transcript = transcript.replace(\"[foreign_language]\", \"<f>\")\n",
    "    transcript = transcript.replace(\"[inaudible]\", \"<u>\")\n",
    "    transcript = transcript.replace(\"[crosstalk]\", \"<u>\")\n",
    "    transcript = transcript.replace(\"[redacted]\", \"<u>\")\n",
    "    transcript = transcript.replace(\"[beep]\", \"<beep>\")\n",
    "    transcript = transcript.replace(\"--\", \" \")\n",
    "    transcript = re.sub(r\"\\[.*?\\]\", \" \", transcript)\n",
    "    teanscript = re.sub(r\"\\bfcuk\\b\", \"fuck\", transcript)\n",
    "    transcript = normalize_whitespace(transcript)\n",
    "    return transcript"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "b2465b35",
   "metadata": {},
   "outputs": [],
   "source": [
    "# jsonl \n",
    "\n",
    "# {\n",
    "#   \"audio\": \"0a4ac9ac-42a4-4e77-91ad-862b0509d913.wav.\", // the audio file name\n",
    "#   \"transcript\": \".....\",  // The transcript of the audio\n",
    "#   \"tags\": [ ]  // The \"OFF\" and/or \"AC\" tags if relevant to the utterance\n",
    "# }\n",
    "# Audio corrupted utterance (AC): for only severely corrupted audio files\n",
    "# Offensive utterance (OFF): profanities, bullying language, hate speech included in the audio file\n",
    "output_metadata = []\n",
    "for n, m in enumerate(segments_manifest):\n",
    "    norm_tokens = Tokens.from_dict(m[\"transcript_normalized\"][\"tokens\"])\n",
    "    tokens = Tokens.from_dict(m[\"transcript\"][\"tokens\"])\n",
    "    norm_transcript = _convert_norm_transcript(norm_tokens)\n",
    "    transcript = _convert_full_transcript(tokens)\n",
    "#     tags = []\n",
    "#     if _contains_profanity(norm_transcript):\n",
    "#         tags.append(\"OFF\")\n",
    "    original_filename = id_to_original_id_map[m[\"id\"]]\n",
    "    \n",
    "#     if \"foreign\" in transcript:\n",
    "#         print(norm_transcript)\n",
    "#         print(\"-\")\n",
    "#         print(transcript)\n",
    "#         print(\"-\"*10)\n",
    "#     if len(norm_transcript) == 0:\n",
    "#         print(norm_transcript)\n",
    "#         print(\"-\")\n",
    "#         print(transcript)\n",
    "#         print(\"-\"*10)\n",
    "        \n",
    "    # some manual overrides\n",
    "    # TODO: use CER here in future to punt and maybe reannotate\n",
    "#     if original_filename == \"c7bfc752-be04-4c91-b018-bf809ad19323.mp3\":\n",
    "#         transcript = transcript.replace(\"Banja not to this barely\", \"[foreign_language] Chef Bally\")\n",
    "#         norm_transcript = norm_transcript.replace(\"we ' re\", \"we're\")\n",
    "#     if original_filename == \"cc6284ac-dc8b-420c-9bd0-8470d2e2d88d.mp3\":\n",
    "#         transcript = \"Damn.\"\n",
    "#         norm_transcript = \"damn\"\n",
    "#         tags = [\"OFF\"]\n",
    "#     if original_filename == \"b451b2ff-0dd2-4a8b-a317-34ea67f172bd.mp3\":\n",
    "#         transcript = transcript.replace(\"I can't\", \"I can't, I can't\")\n",
    "#         norm_transcript = norm_transcript.replace(\"i can't\", \"i can't i can't\")\n",
    "#     if original_filename == \"4600e16e-fd7d-4c69-9e1d-49b1a3c2b088.mp3\":\n",
    "#         transcript = transcript.replace(\"y'all\", \"yo\")\n",
    "#         norm_transcript = norm_transcript.replace(\"y'all\", \"yo\")  \n",
    "#     if original_filename == \"3cd8a90f-8475-4d7c-84f3-07e9b7aa0227.mp3\":\n",
    "#         transcript = \"What?\"\n",
    "#         norm_transcript = \"what\"\n",
    "#     if original_filename == \"558a3f70-8f55-4b7e-9b14-6d6e2a436218.mp3\":\n",
    "#         transcript = \"<u>\"\n",
    "#         norm_transcript = \"[inaudible]\"\n",
    "#     if original_filename == \"35063d27-f049-41d1-a157-417ea07f068c.mp3\":\n",
    "#         transcript = transcript.replace(\"one zero\", \"ten\")\n",
    "\n",
    "    output_metadata.append({\n",
    "        \"audio\": original_filename,\n",
    "        \"transcript\": normalize_whitespace(norm_transcript),\n",
    "        \"transcript_full\": normalize_whitespace(transcript),\n",
    "#         \"tags\": tags,\n",
    "    })"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "1934deee",
   "metadata": {},
   "outputs": [],
   "source": [
    "# reverse IDs\n",
    "original_id_map = {}\n",
    "with open(os.path.join(BASE_DIR, \"raw_data_manifest.json\")) as f:\n",
    "    original_filepaths_info = json.load(f)\n",
    "for e in original_filepaths_info:\n",
    "    original_id_map[e[0]] = get_filename(e[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "ec5ef4cc",
   "metadata": {},
   "outputs": [],
   "source": [
    "out_metas = []\n",
    "for m in output_metadata:\n",
    "    nm = copy.deepcopy(m)\n",
    "    e = original_id_map[get_filename(nm[\"audio\"])]\n",
    "    nm[\"id\"] = e\n",
    "    del nm[\"audio\"]\n",
    "    out_metas.append(nm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "a4e5e127",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'transcript': \"a l c media it's all about everyday leadership conversations and i'm excited about this one on the last podcast we talked about language and culture and how incredibly interconnected they are change one you change the other and this time we're going to talk about the fact that somebody didn't really change their language and their culture and kind of just did a very superficial methodology in making change happen as you know we're known in the industry as change leadership people we're all executive coaches all certified executive coaches and many people know us and think about us about helping with change so we're going to start today with a little story and i look forward to that story and as we listen to the story i want those of you out there really trying hard to recognize how i want to change this culture i want to change things and then we get stuck and we're gonna talk a little bit about how we got stuck and what we could do differently to change that so with that said what did you just hear me say we're gonna work on and tell the audience who you are who'd like to start i'll start so i'm julie b wise i am a coach and a consultant for j l c for the past four years and one of the things i heard is how we can approach change with our language which is what we talked about yesterday or in the last podcast but we also can do it just with subtle moves as well to get people to slowly ease into the change so as not to be this huge change it could be a slow subtle change well said it's almost like once i have some opportunity to internalize the change and the three of you speak about that really well reflection is a way to develop\",\n",
       " 'transcript_full': \"ALC Media. [speaker_change] It's all about everyday leadership conversations. And I'm excited about this one. On the last podcast, we talked about language and culture, and how incredibly interconnected they are. Change one, you change the other. And this time we're going to talk about the fact that somebody didn't really change their language and their culture, and kind of just did a very superficial methodology in making change happen. As you know, we're known in the industry as change leadership people. We're all executive coaches, all certified executive coaches, and many people know us and think about us about helping with change. So we're going to start today with a little story, and I look forward to that story. And, as we listen to the story, I want those of you out there really trying hard to recognize how I want to change this culture. I want to change things. And then we get stuck. And we're gonna talk a little bit about how we got stuck and what we could do differently to change that. So, with that said, what did you just hear me say we're gonna work on? And tell the audience who you are. Who'd like to start? [speaker_change] I'll start. So I'm Julie B. Wise, I am a coach and a consultant for JLC for the past four years. And, one of the things I heard is how we can approach change with our language, which is what we talked about yesterday or in the last podcast. But we also can do it just with subtle moves, as well, to get people to slowly ease into the change, so as not to be this huge change, it could be a slow, subtle change. [speaker_change] Well said. It's almost like once I have some opportunity to internalize the change, and the three of you speak about that really well. Reflection is a way to develop\",\n",
       " 'id': '00beea28-cf89-45e7-b66e-eaa32a61099c'}"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "out_metas[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "00cecd18",
   "metadata": {},
   "outputs": [],
   "source": [
    "write_jsonl(out_metas, os.path.join(ARTIFACTS_DIR, \"delivery_meta.jsonl\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e56a5855",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75be785b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "6b0b614f",
   "metadata": {},
   "source": [
    "## Final QA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "a61aa689",
   "metadata": {},
   "outputs": [],
   "source": [
    "from suno_utils.utils.text import read_jsonl\n",
    "output_metadata = read_jsonl(os.path.join(ARTIFACTS_DIR, \"delivery_meta.jsonl\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "8a5d9f26",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for e in output_metadata:\n",
    "#     if e[\"audio\"] == \"1034ef38-79aa-48de-a908-0dd6a65c1a36.mp3\":\n",
    "#         print(e[\"audio\"], \"- profanity:\", \"OFF\" in e[\"tags\"])\n",
    "#         Audio.from_file(os.path.join(BASE_DIR, \"audio\", e[\"audio\"])).play()\n",
    "#         print(e[\"transcript\"])\n",
    "#         print(\"-\")\n",
    "#         print(e[\"transcript_full\"])\n",
    "#         break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "201ac267",
   "metadata": {},
   "outputs": [],
   "source": [
    "# # figure out rev\n",
    "# with open(os.path.join(TO_REV_DIR, f\"audio_rev_metas.json\")) as f:\n",
    "#     audio_rev_metas = json.load(f)\n",
    "# uid = inv_id_to_original_id_map[\"harrisnt_-7072462733219728682.m4v\"]\n",
    "# for rev_m in audio_rev_metas:\n",
    "#     for seg_m in rev_m[\"segments_meta\"]:\n",
    "#         if seg_m.get(\"orginial_audio_uid\") == uid:\n",
    "#             print(seg_m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "9ccfd86b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# import random\n",
    "# # random ones\n",
    "# # l = [e for e in segments_manifest if len(e[\"transcript\"][\"tokens\"]) == 0]\n",
    "# l = [e for e in output_metadata if len(e[\"transcript\"]) == 0]\n",
    "# random.shuffle(l)\n",
    "# for e in l[:5]:\n",
    "#     print(e[\"audio\"], \"- profanity:\", \"OFF\" in e[\"tags\"])\n",
    "#     Audio.from_file(os.path.join(BASE_DIR, \"audio\", e[\"audio\"])).play()\n",
    "#     print(e[\"transcript\"])\n",
    "#     print(\"-\")\n",
    "#     print(e[\"transcript_full\"])\n",
    "#     print(\"-\"*10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "3e5ea906",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for e in output_metadata:\n",
    "#     if \"Tom Hiddleston\" in e[\"transcript_full\"]:\n",
    "#         print(e[\"audio\"])\n",
    "#         Audio.play_audio(os.path.join(BASE_DIR, \"audio\", e[\"audio\"]))\n",
    "#         print(e[\"transcript\"])\n",
    "#         print(\"-\")\n",
    "#         print(e[\"transcript_full\"])\n",
    "#         print(\"-\"*10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "f3e5cbcf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "057d3d19-8af0-4eef-9dc1-7a991f2efa57\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/2ca8158c-2d68-46b2-acae-f4ab20540cad.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "completely hairless completely hairless or completely covered in hair hey okay that means no mustache steve nothing oh jesus that could be a complete disaster did you call in the lord on that one yes i did on that one and i don't or how completely hair would you have to be no body hair no hair no i mean but how would you when you say completely hair how would you be you mean covered in hair yeah like as in caveman hair yeah i think werewolf werewolf hair yeah all of the above you just talking about what i got now like sister deidra at the church she got hair mustache beard hair in your ears in your nose between your eyes are you talking about no eyebrows no brows no nothing no i'm going take that hair i'm gonna shape it up cause that hairless you fitting to look like just a damn blob you fitting to look like an emoji taking all that back now hey i'm not fitting to be no walking around like no damn emoji now that ain't what i'm fitting to do i ain't got no eyebrows none uh uh no mustache though no dawg i got problems with no eyebrows paint em on lot of women draw em on i know but it's shocking when you get up on it and you discover that it's a drawing that it is artwork you could get em tattooed on it's artwork yeah you can get that done too but you gotta do something else i just don't like to discover that it's artwork that you have none all right all right moving on would you rather sweat profusely in the bedroom or just have insatiable dry mouth just would you rather sweat a lot in the bedroom or just would you like to have a dry mouth all time yeah in the bedrrom no i'm gonna take the sweat\n",
      "-\n",
      "Completely hairless, completely hairless or completely covered in hair. [speaker_change] Hey. [speaker_change] Okay, that means no mustache, Steve, nothing. [speaker_change] Oh Jesus. That could be a complete disaster. [speaker_change] Did you call in the Lord on that one? [speaker_change] Yes, I did on that one and I don't. Or how completely hair would you have to be? [speaker_change] No body hair, no hair. [speaker_change] No, I mean, but how would you, when you say completely hair, how would you be? [speaker_change] You mean covered in hair? [speaker_change] Yeah. Like as in caveman hair? [speaker_change] Yeah, I think. [speaker_change] Werewolf? [speaker_change] Werewolf hair. [speaker_change] Yeah, all of the above. [speaker_change] You just talking about what I got now. [speaker_change] Like Sister Deidra at the church she got hair. [speaker_change] Mustache, beard, Hair in your ears, in your nose, between your eyes. [speaker_change] Are you talking about no eyebrows. [speaker_change] No brows, no nothing. [speaker_change] No, I'm going take that hair, I'm gonna shape it up. Cause that hairless you fitting to look like just a damn blob. You fitting to look like an emoji. [speaker_change] Taking all that back now? [speaker_change] Hey, I'm not fitting to be no walking around like no damn emoji now. That ain't what I'm fitting to do. I ain't got no eyebrows. [speaker_change] None, uh-uh. No mustache though. [speaker_change] No dawg, I got problems with no eyebrows. [speaker_change] Paint em on, lot of women draw em on. [speaker_change] I know, but it's shocking when you get up on it and you discover that it's a drawing that it is artwork. [laughter] [speaker_change] You could get em tattooed on. [speaker_change] It's artwork. [speaker_change] Yeah, you can get that done too. But you gotta do something else. I just don't like to discover that it's artwork that you have none. [speaker_change] All right. All right, moving on. Would you rather sweat profusely in the bedroom or just have insatiable dry mouth? Just would you rather sweat a lot in the bedroom or just would you like to have a dry mouth all time? Yeah in the bedrrom. [speaker_change] No, I'm gonna take the sweat.\n",
      "----------\n",
      "01f4a5ef-5b78-4918-a2cd-eb5ba871e410\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/7fefbb1b-cd3d-4b08-b59e-10e5cf45e0e4.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sixteen and i will read these verses for us for this reason we also constantly thank god that when you the thessalonians received the word of god which you heard from us you accepted it not as the word of men but for what it really is the word of god which also performs its work in you who believe for you brethren became imitators of the churches of god in christ jesus that are in judea for you also endured the same sufferings at the hands of your own countrymen even as they did from the jews who both killed the lord jesus and the prophets and drove us out they are not pleasing to god but hostile to all men hindering us from speaking to the gentiles so that they may be saved with the result that they always fill up the measure of their sins but wrath has come upon them to the utmost let's pray father again we appeal to you in the name of your son jesus christ to speak to us for your name's sake speak to us through this portion teach us what you have for us today i pray in christ's name amen so paul begins this part of his letter by acknowledging his gratitude to god that when these thessalonicans received the word of god which they heard from paul and selvaus and silas that they received it for what it really was the word of god that*\n",
      "-\n",
      "16, and I will read these verses for us. \"For this reason, we also constantly thank God that when you, the Thessalonians, received the word of God, which you heard from us, you accepted it not as the word of men, but for what it really is, the word of God, which also performs its work in you who believe. For you brethren became imitators of the churches of God in Christ Jesus that are in Judea. For you also endured the same sufferings at the hands of your own countrymen, even as they did from the Jews who both killed the Lord Jesus and the prophets and drove us out. They are not pleasing to God, but hostile to all men, hindering us from speaking to the Gentiles so that they may be saved with the result that they always fill up the measure of their sins. But wrath has come upon them to the utmost. Let's pray. Father, again, we appeal to you in the name of your son Jesus Christ, to speak to us for your name's sake. Speak to us through this portion. Teach us what you have for us today. I pray in Christ's name. Amen. So Paul begins this part of his letter by acknowledging his gratitude to God that when these Thessalonicans received the word of God, which they heard from Paul and Selvaus and Silas, that they received it for what it really was, the word of God. That*\n",
      "----------\n",
      "17fcc63d-645b-4ddd-96c2-f9f171dac210\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/7762ec27-9d14-46bb-bf01-398def304d73.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "reminds the grim and gray impression which had been left upon both of us by our first experience of baskerville hall as sir henry and i sat at breakfast the sunlight flooded in through the high mullion windows throwing watery patches of color from the coats of arms which covered them the dark paneling glowed like bronze in the golden rays and it was hard to realize that this was indeed the chamber which had struck such a gloom into our souls the evening before i guess it is ourselves and not the house that we have to blame said the baronet we were tired with our journey and chilled by our drive so we took a gray view of the place now we are fresh and well so it is all cheerful once more and yet it was not entirely a question of imagination i answered did you for example happen to hear someone a woman i think sobbing in the night that is curious for i did when i was half asleep fancy that i heard something of the sort i waited quite a time but there was no more of it so i concluded that it was all a dream i heard it distinctly and i am sure that it was really the sob of a woman we must ask about this right away he rang the bell and asked barrymore whether he could account for our experience it seemed to me that the pallet features of the butler turned a shade paylor still as he listened to his master's question there are only two women in the house sir henry he answered one is the scullery maid who sleeps in the other wing the other is my wife and i can answer for it that the sound could not have come from her and yet he lied as he said it for it chance that after breakfast i met misses barmore in the long corridor with the sun full upon her face she was a large impassive heavy featured woman with a stern set expression of mouth\n",
      "-\n",
      "Reminds the grim and gray impression which had been left upon both of us by our first experience of Baskerville Hall. As Sir Henry and I sat at breakfast, the sunlight flooded in through the high mullion windows, throwing watery patches of color from the coats of arms which covered them. The dark paneling glowed like bronze in the golden rays. And it was hard to realize that this was indeed the chamber which had struck such a gloom into our souls the evening before. \"I guess it is ourselves and not the house \"that we have to blame,\" said the baronet. We were tired with our journey and chilled by our drive. So we took a gray view of the place. Now we are fresh and well. So it is all cheerful once more. And yet it was not entirely a question of imagination, I answered. Did you for example happen to hear someone, a woman I think sobbing in the night. That is curious for I did when I was half asleep fancy that I heard something of the sort. I waited quite a time but there was no more of it. So I concluded that it was all a dream. I heard it distinctly and I am sure that it was really the sob of a woman. We must ask about this right away. He rang the bell and asked Barrymore whether he could account for our experience. It seemed to me that the pallet features of the butler turned a shade Paylor still as he listened to his master's question. \"There are only two women in the house, Sir Henry,\" he answered. One is the scullery maid who sleeps in the other wing. The other is my wife and I can answer for it that the sound could not have come from her. And yet he lied as he said it for it chance that after breakfast I met Mrs. Barmore in the long corridor with the sun full upon her face. She was a large impassive, heavy featured woman with a stern set expression of mouth.\n",
      "----------\n",
      "2407acf3-194f-459a-af03-f5283962180b\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/dd723f79-b340-441e-87f6-99c9bb88eef8.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "be just a tad bit different i thought you know i would really love to start having conversations with people here on the podcast about you know life and happiness and yeah just all of those good things so i thought who better to kick this kind of idea or direction of then my husband because to be honest he contributes a great deal to my own happiness and i know that he contributes you know all the happiness of the people who are in his life and he's just a wonderful individual and has a really positive outlook on life and these are the kind of coffee dates that we enjoy to have like after we get my son off to school or even heck these are the conversations we like to have you know date nights or hiking in the forest like we're always talking about the deeper things in life and i thought i would let you listen in on you know a coffee date with my husband because i always think that there's a you know tidbit of info to learn from his wisdom and love and grace so yeah here it is hope you enjoy welcome to the candid happiness podcast so excited to have you here this morning in our corner of our living room chatting all about life it's awesome it's an honor to to be here thank you for inviting me into something that we can look back on you know five ten years down the road super excited awesome so everyone obviously knows you're my husband but give us a quick intro on who you are ah funny i am a forty year old man i guess almost knocking on forty's door i'm an entrepreneur i own a roofing business here in the negative region i am a father of one a dog lover a son a husband a best friend to you and you know just a regular guy i guess would say\n",
      "-\n",
      "Be just a tad bit different. I thought, you know, I would really love to start having conversations with people here on the podcast about, you know, life and happiness and yeah, just all of those good things. So I thought, who better to kick this kind of idea or direction of then my husband? Because to be honest, he contributes a great deal to my own happiness. And I know that he contributes, you know, all the happiness of the people who are in his life, and he's just a wonderful individual and has a really positive outlook on life. And these are the kind of coffee dates that we enjoy to have, like after we get my son off to school or even heck, these are the conversations we like to have, you know, date nights or hiking in the forest. Like we're always talking about the deeper things in life. And I thought I would let you listen in on, you know, a coffee date with my husband because I always think that there's a, you know, tidbit of info to learn from his wisdom and love and grace. So yeah, here it is. Hope you enjoy. Welcome to the Candid Happiness podcast. So excited to have you here this morning in our corner of our living room chatting all about life. [speaker_change] It's awesome. It's an honor to to be here. Thank you for inviting me into something that we can look back on, you know, five, 10 years down the road. Super excited. [speaker_change] Awesome. So everyone obviously knows you're my husband, but give us a quick intro on who you are. [speaker_change] Ah, funny. I am a forty year old man, I guess. [laughter] [speaker_change] Almost. Knocking on 40's door. [speaker_change] I'm an entrepreneur. I own a roofing business here in the negative region. I am a father of one, a dog lover, a son, a husband, a best friend to you and, you know, just a regular guy I guess would say.\n",
      "----------\n",
      "1dd26b67-8a9f-48ee-8e7c-65f068400cc4\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<audio controls=\"controls\" autobuffer=\"autobuffer\" style=\"width:100%;\">\n",
       "  <source src=\"../../../suno_stream_links/32a12ad9-22dc-43e5-9664-cec088d9b143.wav\"/>\n",
       "  Your browser does not support the audio element.\n",
       "</audio>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i'm good how about you <u> you look amazing thank you so are you serving late thank you we're serving janet jackson right here you know i do feel my little hiphop rock star thing i like it i'm into that we definitely gonna talk about it now we gotta talk about your name okay mika three k's yeah what's the meaning of the three k's so you know how everybody has an alter ego well generally if you know that makes you feel a certain way i feel like it's the reinvention of my alter ego so instead of it being mika who i am is mika two then mika three and i'm also i think more so of generation i'm a real deep thinker so i'm the person in the family that's going to break the generational curses i'm the third one so it's just this is it oh it's mika three k so mika's so everything's threes with me mika's your government name yes okay and we add three so that's your yes i love it that's it's three ks yeah okay great tell us how you got into rap cause you know you're fairly new to the industry so i know you got a story for us yeah so i got into it more so doing hosting and just trying to help other people out with their artistry and stuff and i'm like let me just make a song cause it'll be fun you know let's do a song it'll be fun and then i was like whoa wait and then people listening like wait you can really do good music and it made me excited because in addition to just doing the rapping i can actually create the song so i'm like damn i got it from the hood to the so it just got me excited and then i realized that i use it as a form of therapy i'm the type of person that i don't disagree with therapy but it just doesn't work for me i can't have people that aren't like me tell me or talk to me i can't share but with the music i don't have to be i can be whoever to the freak fuck i wanna be see see when you gotta be a certain way you know what i mean but in your music in your artistry i can do what i want i can say what i want i don't care how anybody feels plus i like to tell stories so that's what it is when it come mika three k my music i like to tell stories too i love it so you first wrote a song and you realized you could rap yes how long ago okay so how did you write the song like this did somebody asked you to write the song was you in the studio playing around\n",
      "-\n",
      "I'm good, How about you? [inaudible] You look amazing. [speaker_change] Thank you. So, are you serving late? Thank you, We're serving Janet Jackson right here. [speaker_change] You know I do feel my little hiphop rock star thing. [speaker_change] I like it. [speaker_change] I'm into that. We definitely gonna talk about it. Now, we gotta talk about your name. [speaker_change] Okay. [speaker_change] Mika three K's. [speaker_change] Yeah. [speaker_change] What's the meaning of the three K's? [speaker_change] So you know how everybody has an alter ego? Well generally if you know that makes you feel a certain way. I feel like it's the reinvention of my alter ego. So instead of it being Mika, who I am is Mika two then Mika three. And I'm also, I think more so of generation, I'm a real deep thinker. So I'm the person in the family that's going to break the generational curses. I'm the third one, so it's just, this is it. [speaker_change] Oh. [speaker_change] It's Mika three K. [speaker_change] So Mika's [speaker_change] So everything's threes with me. Mika's your government name? [speaker_change] Yes. Okay, and we add three, so that's your [speaker_change] Yes. [speaker_change] I love it. [speaker_change] That's it's three Ks yeah. [speaker_change] Okay, great. Tell us how you got into rap, cause you know you're fairly new to the industry, so I know you got a story for us. [speaker_change] Yeah, so I got into it more so doing hosting and just trying to help other people out with their artistry and stuff. And I'm like, let me just make a song cause it'll be fun, you know, let's do a song, it'll be fun. And then I was like, whoa, wait. And then people listening like, wait, you can really do good music. And it made me excited because in addition to just doing the rapping, I can actually create the song. So I'm like, \"Damn I got it from the hood to the So it just got me excited and then I realized that I use it as a form of therapy. I'm the type of person that I don't disagree with therapy, but it just doesn't work for me. I can't have people that aren't like me tell me or talk to me, I can't share. But with the music, I don't have to be, I can be whoever to the freak, fuck I wanna be. See, see when you gotta be a certain way, you know what I mean? But in your music, in your artistry, I can do what I want. I can say what I want. I don't care how anybody feels. Plus I like to tell stories. So that's what it is when it come Mika three K my music, I like to tell stories too. [speaker_change] I love it. So, you first wrote a song and you realized you could rap? [speaker_change] Yes. How long ago? Okay, so how did you write the song like this? Did somebody asked you to write the song? Was you in the studio playing around?\n",
      "----------\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "assert(len(RAW_AUDIO_DIRS) == 1)\n",
    "# random ones\n",
    "# l = [e for e in segments_manifest if len(e[\"transcript\"][\"tokens\"]) == 0]\n",
    "l = output_metadata[:]\n",
    "random.shuffle(l)\n",
    "for e in l[:5]:\n",
    "    print(e[\"id\"])\n",
    "    Audio.play_audio(os.path.join(RAW_AUDIO_DIRS[0], e[\"id\"] + \".wav\"))\n",
    "    print(e[\"transcript\"])\n",
    "    print(\"-\")\n",
    "    print(e[\"transcript_full\"])\n",
    "    print(\"-\"*10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38a9ce1f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "76c34c77",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a33601a9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "9f84953b",
   "metadata": {},
   "source": [
    "## compare with their output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "08368ccc",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18112b59",
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(os.path.join(RAW_DATA_DIR, \"transcripts.tsv\")) as f:\n",
    "    sl_transcripts = [e.split(\"\\t\") for e in f.read().strip().split(\"\\n\")]\n",
    "assert(all([len(e) == 2 for e in sl_transcripts]))\n",
    "sl_transcripts = [(uid, text.lower()) for uid, text in sl_transcripts]\n",
    "print(len(sl_transcripts), \"transcripts\")\n",
    "sl_transcripts[:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e038f68f",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_df = pd.DataFrame(output_metadata).drop([\"tags\"], 1)\n",
    "test_df[\"uid\"] = test_df[\"audio\"].str.split(\".\").str[0]\n",
    "test_df[\"sl_transcript\"] = test_df[\"uid\"].map({k: v for k, v in sl_transcripts})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b1f33880",
   "metadata": {},
   "outputs": [],
   "source": [
    "from suno_utils.utils.metrics import get_wer\n",
    "test_df[\"wer\"] = [get_wer(a, b) for a, b in zip(test_df[\"transcript\"], test_df[\"sl_transcript\"])]\n",
    "test_df = test_df.sort_values(\"wer\", ascending=False).reset_index(drop=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a66aa1b0",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "test_df[test_df[\"transcript\"].str.len() >= 50].head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc008f15",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_df[test_df[\"transcript_full\"].str.contains(r\"\\[\")].head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "faca5ede",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 23\n",
    "row = test_df.iloc[n]\n",
    "Audio.from_file(os.path.join(AUDIO_DIR, row[\"audio\"])).play()\n",
    "print(row[\"uid\"])\n",
    "print(row[\"transcript\"])\n",
    "print(row[\"sl_transcript\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22240080",
   "metadata": {},
   "outputs": [],
   "source": [
    "# segment_uid = \"30815903-8a47-4d14-8557-41c352526d5d\"\n",
    "# segment_uid = \"974c5846-5ae1-4521-9ca2-83175d563c55\"\n",
    "# segment_uid = \"45a812db-16ef-494f-acde-6d151d012a70\"\n",
    "segment_uid = \"6643b5a8-06de-45cb-a99f-351c54d49133\" \n",
    "\n",
    "for n, m in enumerate(audio_rev_metas):\n",
    "    rev_id = m[\"uid\"]\n",
    "    for nn, mm in enumerate(m[\"segments_meta\"]):\n",
    "        if mm[\"type\"] != \"speech\":\n",
    "            continue\n",
    "        if mm[\"orginial_audio_uid\"] == segment_uid:\n",
    "            print(n, nn)\n",
    "            print(audio_rev_metas[n][\"uid\"])\n",
    "            print(audio_rev_metas[n][\"segments_meta\"][nn])\n",
    "#             print(Tokens.from_dict(e[\"transcript\"][\"tokens\"]).text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41a7cdec",
   "metadata": {},
   "source": [
    "gsutil -m cp /mnt/data-ssd-1/data/private/customer/speechly/2022-11-06_multilingual-50h/pipeline/2022_11_06/artifacts/en_tiktok_delivery_meta.jsonl gs://speechly-suno-wtyfeusyax/titktok/output/en_annotations.jsonl\n",
    "\n",
    "gsutil -m cp /mnt/data-ssd-1/data/private/customer/speechly/2022-11-06_multilingual-50h/pipeline/2022_11_06/artifacts/en_youtube_delivery_meta.jsonl gs://speechly-suno-wtyfeusyax/youtube/output/en_annotations.jsonl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7fc6b380",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5054cd12",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc513d9e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d51f20f8",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "36ae3093",
   "metadata": {},
   "source": [
    "## Playground"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd4d76ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import numpy as np\n",
    "from suno_utils.audio import Audio\n",
    "\n",
    "tt_d = \"/mnt/data-ssd-1/data/private/customer/speechly/gcp_bucket/titktok/multilingual-50h/en/\"\n",
    "tt_fns = [fn for fn in os.listdir(tt_d) if fn.endswith(\".wav\")]\n",
    "yt_d = \"/mnt/data-ssd-1/data/private/customer/speechly/gcp_bucket/youtube/multilingual-50h/en/\"\n",
    "yt_fns = [fn for fn in os.listdir(yt_d) if fn.endswith(\".wav\")]\n",
    "print(\n",
    "    round(np.sum([\n",
    "        Audio.get_details(os.path.join(tt_d, fn), attempt_using_header=True)[\"duration_s\"] for fn in tt_fns\n",
    "    ]) / 60 / 60, 1), \n",
    "    \"hours of tiktok\"\n",
    ")\n",
    "print(\n",
    "    round(np.sum([\n",
    "        Audio.get_details(os.path.join(yt_d, fn), attempt_using_header=True)[\"duration_s\"] for fn in yt_fns\n",
    "    ]) / 60 / 60, 1), \n",
    "    \"hours of youtube\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "365702d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: mistake\n",
    "#   It says to read verse 20, 1st John 3:20.\n",
    "#   Zero, teo, zero. Episode page"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "a0b2e806",
   "metadata": {},
   "outputs": [],
   "source": [
    "transcript_tokens = Tokens.from_text(\"It says to read verse 20, 1st John 3:20. Zero, teo, zero. Episode page\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "b9674b89",
   "metadata": {},
   "outputs": [],
   "source": [
    "from suno_utils.customers.sanas.pipeline import _digitify, _find_valid_indicators"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "dda2a125",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "20\n",
      "1\n",
      "\n",
      "320\n",
      "0\n",
      "\n",
      "0\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "indicator_speaker_id = None\n",
    "\n",
    "indicator_tokens = []\n",
    "prev_n = -2\n",
    "last_speaker_id = None\n",
    "for n, token in enumerate(transcript_tokens):\n",
    "    # if we know indicator speaker id then skip others\n",
    "    if indicator_speaker_id is not None and indicator_speaker_id != token.speaker_id:\n",
    "        last_speaker_id = token.speaker_id\n",
    "        continue\n",
    "    parsed_number = _digitify(token.value)\n",
    "    print(parsed_number)\n",
    "    if len(parsed_number) == 0:\n",
    "        last_speaker_id = token.speaker_id\n",
    "        continue\n",
    "    # if multiple tokens in a row pass then add to previous\n",
    "    if n - prev_n == 1 and last_speaker_id == token.speaker_id:\n",
    "        indicator_tokens[-1] = (\n",
    "            indicator_tokens[-1][0],\n",
    "            indicator_tokens[-1][1] + parsed_number,\n",
    "        )\n",
    "    elif token.speaker_id is None or last_speaker_id != token.speaker_id:\n",
    "        indicator_tokens.append((n, parsed_number))\n",
    "    else:\n",
    "        # TODO: if not new speaker then we don't add?\n",
    "        last_speaker_id = token.speaker_id\n",
    "        continue\n",
    "    prev_n = n\n",
    "    last_speaker_id = token.speaker_id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a53ef220",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac828916",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "88b9adb8",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50209cc1",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "055c42ab",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff7c5d47",
   "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.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
