{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "dd91bab8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# setup tailscale if you haven't\n",
    "# https://tailscale.com/kb/1031/install-linux\n",
    "!sudo tailscale up --accept-routes=true\n",
    "\n",
    "# setup autoload\n",
    "%load_ext autoreload\n",
    "\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "efef51bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# make sure sqlalchemy is >=2\n",
    "# pip install psycopg2-binary\n",
    "# pip install \"sqlalchemy>=2\"\n",
    "import os\n",
    "import datetime\n",
    "from collections import defaultdict, Counter\n",
    "import json\n",
    "from urllib.parse import quote\n",
    "import time\n",
    "\n",
    "import boto3\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import sqlalchemy\n",
    "import tqdm\n",
    "from botocore.exceptions import ClientError\n",
    "from suno_analytics.preference_helper import (\n",
    "    get_preference_counts,\n",
    "    plot_preference_data_for_each_task,\n",
    ")\n",
    "from suno_analytics.preference_data_selection import (\n",
    "    gather_data,\n",
    "    gather_data_with_snowflake,\n",
    "    plot_clip_distribution,\n",
    "    parse_metadata_for_basics,\n",
    "    get_concat_clip_ids,\n",
    "    validate_preference_data,\n",
    "    run_bot_detection,\n",
    "    print_out_value_counts_nicely,\n",
    "    merge_concat_clips_with_reactions,\n",
    "    plot_clip_basic_distributions,\n",
    "    run_bot_detection_old,\n",
    ")\n",
    "\n",
    "\n",
    "# setup some pandas display stuff\n",
    "pd.set_option(\"display.max_rows\", 500)\n",
    "pd.set_option(\"display.max_columns\", 500)\n",
    "pd.set_option(\"display.width\", 1000)\n",
    "\n",
    "\n",
    "def get_secret():\n",
    "    secret_name = \"app-user-main-db-secret\"\n",
    "    region_name = \"us-east-2\"\n",
    "    # Create a Secrets Manager client\n",
    "    session = boto3.session.Session()\n",
    "    client = session.client(service_name=\"secretsmanager\", region_name=region_name)\n",
    "    try:\n",
    "        get_secret_value_response = client.get_secret_value(SecretId=secret_name)\n",
    "    except ClientError as e:\n",
    "        raise e\n",
    "    secret = get_secret_value_response[\"SecretString\"]\n",
    "    return json.loads(secret)\n",
    "\n",
    "\n",
    "my_secrets = get_secret()\n",
    "\n",
    "# alternative...\n",
    "engine = sqlalchemy.create_engine(\n",
    "    \"postgresql://suno:%s@suno-main-postgres-prod-analytics.cnfvffydbwvc.us-east-2.rds.amazonaws.com/suno_main\"\n",
    "    % quote(my_secrets[\"password\"]),\n",
    ")\n",
    "\n",
    "\n",
    "home_dir = os.path.expanduser(\"~\")\n",
    "# snow_password_path = os.path.join(home_dir, \".aws\", \"snow_pw.txt\")\n",
    "snow_username = \"TONY\"\n",
    "snow_password_path = os.path.join(home_dir, \".ssh\", \"rsa_key.p8\")\n",
    "if os.path.exists(snow_password_path):\n",
    "    # !pip install snowflake\n",
    "    from snowflake.core import Root\n",
    "    from snowflake.snowpark import Session\n",
    "\n",
    "    # with open(snow_password_path, \"r\") as fp:\n",
    "    #     fp_lines = fp.readlines()\n",
    "    #     snow_password = fp_lines[0].strip()\n",
    "    #     snow_username = fp_lines[1].strip()\n",
    "\n",
    "    CONNECTION_PARAMETERS = {\n",
    "        \"account\": \"fu90569.us-east-2.aws\",\n",
    "        \"user\": snow_username,\n",
    "        # \"password\": snow_password,\n",
    "        \"private_key_file\": snow_password_path,\n",
    "        \"role\": \"ACCOUNTADMIN\",\n",
    "        \"database\": \"SUNO_PROD\",\n",
    "        \"warehouse\": \"SUNO_PROD_LARGE\",\n",
    "        \"schema\": \"PROD\",\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "33cf3916",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_all_tables = pd.read_sql_query(\n",
    "    \"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\",\n",
    "    engine,\n",
    ")\n",
    "# should have all the basic table names here\n",
    "assert df_all_tables[\"table_name\"].nunique() >= 61"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c752a21c",
   "metadata": {},
   "outputs": [],
   "source": [
    "user_upload_df = pd.read_sql_query(\n",
    "    \"\"\"\n",
    "    SELECT *\n",
    "    FROM bots_audioupload\n",
    "    WHERE upload_type = 'file_upload'\n",
    "      AND duration > 30\n",
    "      AND error_type IS NULL\n",
    "      AND created_at >= '2025-06-01'\n",
    "      AND created_at < '2025-09-01'\n",
    "    \"\"\",\n",
    "    engine,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "1bbc5d79",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>updated_at</th>\n",
       "      <th>audio_s3_id</th>\n",
       "      <th>error_type</th>\n",
       "      <th>upload_type</th>\n",
       "      <th>created_at</th>\n",
       "      <th>clip_id</th>\n",
       "      <th>user_id</th>\n",
       "      <th>duration</th>\n",
       "      <th>has_vocal</th>\n",
       "      <th>image_s3_id</th>\n",
       "      <th>requested_clip_id</th>\n",
       "      <th>title</th>\n",
       "      <th>inferred_lyrics</th>\n",
       "      <th>inferred_description</th>\n",
       "      <th>display_tags</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>5582620</th>\n",
       "      <td>70595dc0-428c-4acd-9c6e-3da7673c296a</td>\n",
       "      <td>2025-08-20 19:48:04.116971+00:00</td>\n",
       "      <td>0cded547-c1f7-476e-8696-eaf4c2fa7ee8</td>\n",
       "      <td>None</td>\n",
       "      <td>file_upload</td>\n",
       "      <td>2025-08-20 19:48:02.657903+00:00</td>\n",
       "      <td>0cded547-c1f7-476e-8696-eaf4c2fa7ee8</td>\n",
       "      <td>103054539</td>\n",
       "      <td>213.360000</td>\n",
       "      <td>False</td>\n",
       "      <td>image_0cded547-c1f7-476e-8696-eaf4c2fa7ee8</td>\n",
       "      <td>0cded547-c1f7-476e-8696-eaf4c2fa7ee8</td>\n",
       "      <td>زِِدْنِي حَنِينًا يَا رَسُولَ العَاشِقِي (5)</td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582621</th>\n",
       "      <td>c12b42f4-88d1-4918-b254-3dc7b15ba8c5</td>\n",
       "      <td>2025-08-20 19:48:03.709910+00:00</td>\n",
       "      <td>a6585c24-4e4e-45d2-ad5c-78cc2f47b34e</td>\n",
       "      <td>None</td>\n",
       "      <td>file_upload</td>\n",
       "      <td>2025-08-20 19:48:03.709894+00:00</td>\n",
       "      <td>None</td>\n",
       "      <td>107783455</td>\n",
       "      <td>35.040000</td>\n",
       "      <td>False</td>\n",
       "      <td>image_a6585c24-4e4e-45d2-ad5c-78cc2f47b34e</td>\n",
       "      <td>a6585c24-4e4e-45d2-ad5c-78cc2f47b34e</td>\n",
       "      <td>KenyX - pa la pared 2025-08-20 15_47</td>\n",
       "      <td>[Verse 1]\\nPila cacho, bótame la llave como An...</td>\n",
       "      <td>A high-energy reggaeton track in a minor key, ...</td>\n",
       "      <td>reggaeton, aggressive, raw male vocals</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582622</th>\n",
       "      <td>0372708d-9407-4036-aeb3-b780432a3eac</td>\n",
       "      <td>2025-08-20 19:48:05.604194+00:00</td>\n",
       "      <td>c6d2907d-e96a-4703-bf54-bab5af29d093</td>\n",
       "      <td>None</td>\n",
       "      <td>file_upload</td>\n",
       "      <td>2025-08-20 19:48:04.918854+00:00</td>\n",
       "      <td>c6d2907d-e96a-4703-bf54-bab5af29d093</td>\n",
       "      <td>16688916</td>\n",
       "      <td>99.709388</td>\n",
       "      <td>True</td>\n",
       "      <td>image_c6d2907d-e96a-4703-bf54-bab5af29d093</td>\n",
       "      <td>c6d2907d-e96a-4703-bf54-bab5af29d093</td>\n",
       "      <td>steel samurai rock</td>\n",
       "      <td>[Instrumental]</td>\n",
       "      <td>A high-energy electronic rock track with a dri...</td>\n",
       "      <td>electronic rock, instrumental, high-energy</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582623</th>\n",
       "      <td>21f4db84-325a-4a73-ab08-bf567665e85a</td>\n",
       "      <td>2025-08-20 19:48:07.347646+00:00</td>\n",
       "      <td>58f33bb7-2501-41bf-945e-352ca5dbe44d</td>\n",
       "      <td>None</td>\n",
       "      <td>file_upload</td>\n",
       "      <td>2025-08-20 19:48:05.661763+00:00</td>\n",
       "      <td>58f33bb7-2501-41bf-945e-352ca5dbe44d</td>\n",
       "      <td>33096015</td>\n",
       "      <td>480.000000</td>\n",
       "      <td>False</td>\n",
       "      <td>image_58f33bb7-2501-41bf-945e-352ca5dbe44d</td>\n",
       "      <td>58f33bb7-2501-41bf-945e-352ca5dbe44d</td>\n",
       "      <td>ARTUR NADAL MESCLA V2</td>\n",
       "      <td>[Verse 1]\\nAquest el conec, té la cara d'en Ma...</td>\n",
       "      <td>A dramatic musical theater piece with a male t...</td>\n",
       "      <td></td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582624</th>\n",
       "      <td>a55a0766-4ee7-45db-9a10-7a2713fd3b15</td>\n",
       "      <td>2025-08-20 19:48:06.895333+00:00</td>\n",
       "      <td>3bfa5897-aea4-4e54-8793-26c25f60ef8c</td>\n",
       "      <td>None</td>\n",
       "      <td>file_upload</td>\n",
       "      <td>2025-08-20 19:48:06.287946+00:00</td>\n",
       "      <td>3bfa5897-aea4-4e54-8793-26c25f60ef8c</td>\n",
       "      <td>100303290</td>\n",
       "      <td>165.168000</td>\n",
       "      <td>True</td>\n",
       "      <td>image_3bfa5897-aea4-4e54-8793-26c25f60ef8c</td>\n",
       "      <td>3bfa5897-aea4-4e54-8793-26c25f60ef8c</td>\n",
       "      <td>Blues 2</td>\n",
       "      <td>[Instrumental]</td>\n",
       "      <td>A high-energy rock anthem with a driving rhyth...</td>\n",
       "      <td>rock, hard rock, guitar-driven</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                           id                       updated_at                           audio_s3_id error_type  upload_type                       created_at                               clip_id    user_id    duration  has_vocal                                 image_s3_id                     requested_clip_id                                         title                                    inferred_lyrics                               inferred_description                                display_tags\n",
       "5582620  70595dc0-428c-4acd-9c6e-3da7673c296a 2025-08-20 19:48:04.116971+00:00  0cded547-c1f7-476e-8696-eaf4c2fa7ee8       None  file_upload 2025-08-20 19:48:02.657903+00:00  0cded547-c1f7-476e-8696-eaf4c2fa7ee8  103054539  213.360000      False  image_0cded547-c1f7-476e-8696-eaf4c2fa7ee8  0cded547-c1f7-476e-8696-eaf4c2fa7ee8  زِِدْنِي حَنِينًا يَا رَسُولَ العَاشِقِي (5)                                                                                                                                                  \n",
       "5582621  c12b42f4-88d1-4918-b254-3dc7b15ba8c5 2025-08-20 19:48:03.709910+00:00  a6585c24-4e4e-45d2-ad5c-78cc2f47b34e       None  file_upload 2025-08-20 19:48:03.709894+00:00                                  None  107783455   35.040000      False  image_a6585c24-4e4e-45d2-ad5c-78cc2f47b34e  a6585c24-4e4e-45d2-ad5c-78cc2f47b34e          KenyX - pa la pared 2025-08-20 15_47  [Verse 1]\\nPila cacho, bótame la llave como An...  A high-energy reggaeton track in a minor key, ...      reggaeton, aggressive, raw male vocals\n",
       "5582622  0372708d-9407-4036-aeb3-b780432a3eac 2025-08-20 19:48:05.604194+00:00  c6d2907d-e96a-4703-bf54-bab5af29d093       None  file_upload 2025-08-20 19:48:04.918854+00:00  c6d2907d-e96a-4703-bf54-bab5af29d093   16688916   99.709388       True  image_c6d2907d-e96a-4703-bf54-bab5af29d093  c6d2907d-e96a-4703-bf54-bab5af29d093                            steel samurai rock                                     [Instrumental]  A high-energy electronic rock track with a dri...  electronic rock, instrumental, high-energy\n",
       "5582623  21f4db84-325a-4a73-ab08-bf567665e85a 2025-08-20 19:48:07.347646+00:00  58f33bb7-2501-41bf-945e-352ca5dbe44d       None  file_upload 2025-08-20 19:48:05.661763+00:00  58f33bb7-2501-41bf-945e-352ca5dbe44d   33096015  480.000000      False  image_58f33bb7-2501-41bf-945e-352ca5dbe44d  58f33bb7-2501-41bf-945e-352ca5dbe44d                         ARTUR NADAL MESCLA V2  [Verse 1]\\nAquest el conec, té la cara d'en Ma...  A dramatic musical theater piece with a male t...                                            \n",
       "5582624  a55a0766-4ee7-45db-9a10-7a2713fd3b15 2025-08-20 19:48:06.895333+00:00  3bfa5897-aea4-4e54-8793-26c25f60ef8c       None  file_upload 2025-08-20 19:48:06.287946+00:00  3bfa5897-aea4-4e54-8793-26c25f60ef8c  100303290  165.168000       True  image_3bfa5897-aea4-4e54-8793-26c25f60ef8c  3bfa5897-aea4-4e54-8793-26c25f60ef8c                                       Blues 2                                     [Instrumental]  A high-energy rock anthem with a driving rhyth...              rock, hard rock, guitar-driven"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "user_upload_df.tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "aa192507",
   "metadata": {},
   "outputs": [],
   "source": [
    "from suno_utils.utils.s3 import _get_client"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4ab48229",
   "metadata": {},
   "outputs": [],
   "source": [
    "local_s3_client = _get_client()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "960e7ebb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5582625, 16)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "user_upload_df.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "034f41e9",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Fetching S3 files: 100%|██████████| 5582625/5582625 [3:01:40<00:00, 512.13it/s]   \n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>s3_exists</th>\n",
       "      <th>s3_file_count</th>\n",
       "      <th>s3_files</th>\n",
       "      <th>duration</th>\n",
       "      <th>title</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>82695fc5-7e67-49c6-81d0-f3306ba6978c</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[wav]</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>Linken Poo - 5:26:25, 7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>14f93add-04de-4fc1-92fd-7d82fcd01def</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[mp3]</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>Hey! I Love You! - Hasil (4)_1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>a90bf615-c08b-482c-98a4-19c03d890401</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[mp3]</td>\n",
       "      <td>51.654792</td>\n",
       "      <td>Sesame Street   Lucky 13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>09ace922-b4fa-44aa-9860-dcb930956714</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[wav]</td>\n",
       "      <td>120.000000</td>\n",
       "      <td>Hold On Remix B_1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5582c073-bb6d-4daa-b9a8-52543103239c</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[mp3]</td>\n",
       "      <td>60.000000</td>\n",
       "      <td>Amsal Mitike _ ወይ ወሎ _  Ethiopian Music 2019 M...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582620</th>\n",
       "      <td>70595dc0-428c-4acd-9c6e-3da7673c296a</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[mp3]</td>\n",
       "      <td>213.360000</td>\n",
       "      <td>زِِدْنِي حَنِينًا يَا رَسُولَ العَاشِقِي (5)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582621</th>\n",
       "      <td>c12b42f4-88d1-4918-b254-3dc7b15ba8c5</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[m4a]</td>\n",
       "      <td>35.040000</td>\n",
       "      <td>KenyX - pa la pared 2025-08-20 15_47</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582622</th>\n",
       "      <td>0372708d-9407-4036-aeb3-b780432a3eac</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[mp3]</td>\n",
       "      <td>99.709388</td>\n",
       "      <td>steel samurai rock</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582623</th>\n",
       "      <td>21f4db84-325a-4a73-ab08-bf567665e85a</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[wav]</td>\n",
       "      <td>480.000000</td>\n",
       "      <td>ARTUR NADAL MESCLA V2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5582624</th>\n",
       "      <td>a55a0766-4ee7-45db-9a10-7a2713fd3b15</td>\n",
       "      <td>True</td>\n",
       "      <td>1</td>\n",
       "      <td>[m4a]</td>\n",
       "      <td>165.168000</td>\n",
       "      <td>Blues 2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5582625 rows × 6 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                           id  s3_exists  s3_file_count s3_files    duration                                              title\n",
       "0        82695fc5-7e67-49c6-81d0-f3306ba6978c       True              1    [wav]   60.000000                            Linken Poo - 5:26:25, 7\n",
       "1        14f93add-04de-4fc1-92fd-7d82fcd01def       True              1    [mp3]   60.000000                     Hey! I Love You! - Hasil (4)_1\n",
       "2        a90bf615-c08b-482c-98a4-19c03d890401       True              1    [mp3]   51.654792                           Sesame Street   Lucky 13\n",
       "3        09ace922-b4fa-44aa-9860-dcb930956714       True              1    [wav]  120.000000                                  Hold On Remix B_1\n",
       "4        5582c073-bb6d-4daa-b9a8-52543103239c       True              1    [mp3]   60.000000  Amsal Mitike _ ወይ ወሎ _  Ethiopian Music 2019 M...\n",
       "...                                       ...        ...            ...      ...         ...                                                ...\n",
       "5582620  70595dc0-428c-4acd-9c6e-3da7673c296a       True              1    [mp3]  213.360000       زِِدْنِي حَنِينًا يَا رَسُولَ العَاشِقِي (5)\n",
       "5582621  c12b42f4-88d1-4918-b254-3dc7b15ba8c5       True              1    [m4a]   35.040000               KenyX - pa la pared 2025-08-20 15_47\n",
       "5582622  0372708d-9407-4036-aeb3-b780432a3eac       True              1    [mp3]   99.709388                                 steel samurai rock\n",
       "5582623  21f4db84-325a-4a73-ab08-bf567665e85a       True              1    [wav]  480.000000                              ARTUR NADAL MESCLA V2\n",
       "5582624  a55a0766-4ee7-45db-9a10-7a2713fd3b15       True              1    [m4a]  165.168000                                            Blues 2\n",
       "\n",
       "[5582625 rows x 6 columns]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from typing import Any, List\n",
    "import logging\n",
    "from botocore.exceptions import ClientError\n",
    "import os\n",
    "from concurrent.futures import ThreadPoolExecutor, as_completed\n",
    "from tqdm import tqdm\n",
    "\n",
    "\n",
    "def list_s3_file_extensions_for_id(\n",
    "    s3_client: Any,\n",
    "    bucket: str,\n",
    "    prefix: str,\n",
    "    object_id: str,\n",
    ") -> List[str]:\n",
    "    \"\"\"List all file extensions in S3 under the given prefix/object_id.\n",
    "\n",
    "    Args:\n",
    "        s3_client (Any): The S3 client instance.\n",
    "        bucket (str): The S3 bucket name.\n",
    "        prefix (str): The prefix path in the bucket.\n",
    "        object_id (str): The id to check for files.\n",
    "\n",
    "    Returns:\n",
    "        List[str]: List of file extensions (e.g., ['wav', 'mp3']) found under the prefix/object_id.\n",
    "\n",
    "    Example:\n",
    "        >>> list_s3_file_extensions_for_id(local_s3_client, \"suno-uploads\", \"raw_uploads\", \"a936183c-8f72-4499-8390-5d365b99d70c\")\n",
    "        ['wav', ...]\n",
    "    \"\"\"\n",
    "    s3_prefix = f\"{prefix}/{object_id}\"\n",
    "    try:\n",
    "        paginator = s3_client.get_paginator(\"list_objects_v2\")\n",
    "        page_iterator = paginator.paginate(Bucket=bucket, Prefix=s3_prefix)\n",
    "        extensions: List[str] = []\n",
    "        for page in page_iterator:\n",
    "            if \"Contents\" in page:\n",
    "                for obj in page[\"Contents\"]:\n",
    "                    _, ext = os.path.splitext(obj[\"Key\"])\n",
    "                    if ext:\n",
    "                        extensions.append(ext.lstrip(\".\"))\n",
    "        return extensions\n",
    "    except ClientError as e:\n",
    "        logging.warning(f\"Error listing S3 files for {s3_prefix}: {e}\")\n",
    "        return []\n",
    "\n",
    "\n",
    "bucket_name: str = \"suno-uploads\"\n",
    "prefix: str = \"raw_uploads\"\n",
    "\n",
    "\n",
    "def get_s3_file_extensions_for_row(object_id: str) -> List[str]:\n",
    "    \"\"\"Wrapper for list_s3_file_extensions_for_id for DataFrame apply.\"\"\"\n",
    "    return list_s3_file_extensions_for_id(\n",
    "        local_s3_client, bucket_name, prefix, str(object_id)\n",
    "    )\n",
    "\n",
    "\n",
    "def fetch_s3_files_multithreaded(\n",
    "    ids: List[str],\n",
    "    max_workers: int = 32,\n",
    ") -> List[List[str]]:\n",
    "    \"\"\"Fetch S3 file extensions for a list of object_ids using multithreading.\n",
    "\n",
    "    Args:\n",
    "        ids (List[str]): List of object IDs.\n",
    "        max_workers (int): Number of threads to use.\n",
    "\n",
    "    Returns:\n",
    "        List[List[str]]: List of file extension lists, in the same order as ids.\n",
    "    \"\"\"\n",
    "    results: List[List[str]] = [None] * len(ids)\n",
    "    with ThreadPoolExecutor(max_workers=max_workers) as executor:\n",
    "        future_to_idx = {\n",
    "            executor.submit(get_s3_file_extensions_for_row, object_id): idx\n",
    "            for idx, object_id in enumerate(ids)\n",
    "        }\n",
    "        # tqdm for progress visualization\n",
    "        for future in tqdm(\n",
    "            as_completed(future_to_idx), total=len(ids), desc=\"Fetching S3 files\"\n",
    "        ):\n",
    "            idx = future_to_idx[future]\n",
    "            try:\n",
    "                results[idx] = future.result()\n",
    "            except Exception as e:\n",
    "                logging.warning(f\"Error fetching S3 files for id {ids[idx]}: {e}\")\n",
    "                results[idx] = []\n",
    "    return results\n",
    "\n",
    "\n",
    "# Use multithreading to fetch S3 file info for all rows\n",
    "object_ids: List[str] = user_upload_df[\"id\"].astype(str).tolist()\n",
    "user_upload_df[\"s3_files\"] = fetch_s3_files_multithreaded(object_ids)\n",
    "user_upload_df[\"s3_file_count\"] = user_upload_df[\"s3_files\"].apply(len)\n",
    "user_upload_df[\"s3_exists\"] = user_upload_df[\"s3_file_count\"] > 0\n",
    "\n",
    "# Display the DataFrame with S3 file info (now s3_files contains only extensions)\n",
    "user_upload_df[[\"id\", \"s3_exists\", \"s3_file_count\", \"s3_files\", \"duration\", \"title\"]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a61bdd76",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "S3 file extension counts:\n",
      "mp3     3980502\n",
      "wav     1099265\n",
      "m4a      315889\n",
      "mp4      132611\n",
      "ogg       52626\n",
      "webm        911\n",
      "mov         821\n",
      "Name: count, dtype: int64\n",
      "\n",
      "S3 file extension fractions:\n",
      "mp3     0.713016\n",
      "wav     0.196908\n",
      "m4a     0.056584\n",
      "mp4     0.023754\n",
      "ogg     0.009427\n",
      "webm    0.000163\n",
      "mov     0.000147\n",
      "Name: count, dtype: float64\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAGGCAYAAADmRxfNAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABF5UlEQVR4nO3deVhUdeP+8XsQSBElttTUUEBxDywwBeMR7ZePZqXmUqmZS2pqueWSWblipra4pOW+50pqhpZlaS5Yau5LWrmhsSUqKsrM7w+/zuMEGjDCgeb9ui6uy/nMmZl7GMC553w+55gsFotFAAAAAGAHJ6MDAAAAACj8KBYAAAAA7EaxAAAAAGA3igUAAAAAu1EsAAAAANiNYgEAAADAbhQLAAAAAHajWAAAAACwG8UCAAAAgN0oFgBQALRv317t27e3Xj59+rSCgoK0cuVKA1MVLn//HgIA8pez0QEAwEhHjhzRlClTtG/fPiUmJur+++9XYGCgoqKibN6kTps2Td9++61Onjypy5cvq0yZMoqMjFSPHj3k5eX1j48TFBSU5biPj49+/PHHe/Z8cpNBktq0aaMRI0bk6P4WLlyoYsWKqUWLFvZG+1dITEzUzJkz9d133yk+Pl4mk0n+/v5q1KiR2rVrp5IlSxodUWvWrFFSUpI6duxodBQA/0IUCwAOa9euXerQoYMefPBBtWrVSr6+voqPj9cvv/yiefPm2RSLAwcOqEqVKmrSpImKFy+uEydOaOnSpfr+++8VExMjNze3f3y88PBwPfPMMzZjRYsWlSTNnDnz3j65HGSQpIoVK+b4vhYvXixPT88CUyzy63uYlb179+qVV15RWlqann76aVWvXl2StH//fn322Wf66aefNGvWLMPy3bJ27VodO3aMYgEgT1AsADisadOmqUSJElq+fHmmT5OTkpJsLk+aNCnT7YODg/Xaa6/pu+++U9OmTf/x8SpUqJDlm3pJcnV1zUHy3LtbhsIuv76Hf5eamqpevXqpSJEiWrVqlQICAmyu79u3r5YuXWpINgDIT6yxAOCwTp48qcDAwCynqHh7e//j7cuWLSvp5htLe2V3fcDx48f12muvKSwsTDVr1lSLFi20ceNGux//9vuvVauWBg4caDP+008/qWrVqnr//fclSVFRUTp27Jji4uIUFBSkoKAgm/ypqakaPXq0IiMjVaNGDT3xxBP69NNPZTabrdvcWkcyc+ZMff7552rUqJFq1Kihli1bau/evTaPn5CQoCFDhujxxx9XjRo1FBERoR49euj06dPWbbL6HiYlJenNN99UvXr1VLNmTT399NNatWqVzTY5yZGVJUuW6Pz58xo8eHCmUiHdnO726quv2owtXLhQTZs2tT6X4cOHZ/o5ioqK0uDBgzPd39+f544dOxQUFKR169bpk08+0eOPP66aNWvqpZde0h9//GFzu02bNunMmTPW1ywqKsp6/fz589W0aVM9/PDDCg0NVYsWLbRmzZp/fP4AcAt7LAA4rLJly2r37t06evSoKleu/I/bWywWpaSkKCMjQ3/88YfGjx+vIkWKKCwsLFuPd+3aNSUnJ9uMubu7Z/uT9mPHjun5559XqVKl1LVrV7m5uemrr75Sz549NWnSJD3xxBO5ynB7joCAAL3++usaN26cnnzySTVs2FBpaWkaMmSI/P399frrr0uS3nzzTY0cOVJubm7q3r27pJtvoCXpypUrateunc6fP6+2bduqTJky2r17tyZOnKiEhAQNHTrU5rHXrl2ry5cvq02bNjKZTJoxY4Z69+6tb775Ri4uLpKk3r1769dff1W7du1UtmxZJScn68cff1R8fLzKlSuX5XO9evWq2rdvr5MnT+rFF19UuXLlFBsbq8GDBys1NVUvvfRSjnNk5dtvv1XRokX15JNP/uP3X7q592vy5MmqV6+enn/+ef32229avHix9u3bp8WLF9/1se7ms88+k8lkUqdOnXTp0iXNmDFDAwYM0LJlyyRJ3bt318WLF3Xu3DkNGTJEklS8eHFJ0tKlSzVq1Cg9+eST6tChg65du6YjR47ol19+UbNmzXKVB4DjoVgAcFidOnVS165d9eyzz6pWrVp65JFHVLduXdWpUyfLN3eJiYmKiIiwXi5durTGjx+f5afUWVm+fLmWL19uMxYdHZ3tNQqjR49WmTJltGLFCmsZeeGFF/T8889r/Pjx2SoWWWWQpIkTJ1qnc7388svauHGj3n77bdWuXVuTJk3S2bNntWTJEuvjNmrUSB9++KE8PT0zTa2aPXu2Tp06pVWrVqlChQqSpLZt2+qBBx7QzJkz1alTJ5UpU8a6/dmzZ7VhwwZ5eHhIurne49VXX9WWLVvUoEEDpaamavfu3Ro4cKA6d+5svV23bt3u+lw///xzHT9+XO+//76efvppa4727dvrww8/VMuWLeXu7p7tHHdy4sQJVahQIVsFMTk5WdOnT1dERIQ+++wzOTndnDjg7++vESNGaPXq1WrZsuU/3k9Wrl27ppiYGGuOkiVLavTo0dbiHB4ernnz5ik1NTXTa7Zp0yZVqlRJH3/8ca4eGwAkpkIBcGDh4eFasmSJoqKidPjwYc2YMUOdO3fW448/nuX0Ig8PD82ePVvTpk3Ta6+9Jk9PT6WlpWX78Ro2bKjZs2fbfN1eVO7mr7/+0vbt2/Xf//5Xly5dUnJyspKTk5WSkqKIiAj9/vvvOn/+fK4yzJ49W3Xq1LFu4+TkpLFjxyotLU1du3bVokWL9Morr6hmzZrZyhobG6tHHnlEJUuWtOZMTk5WvXr1lJGRoZ07d9ps36RJE+ubeUl69NFHJUmnTp2SdHOBu4uLi+Li4nThwoVsZZCkH374Qb6+vnrqqaesYy4uLmrfvr3S0tJynONOLl26ZP3k/59s3bpV169fV4cOHaylQpJatWold3d3ff/999m6n6y0aNHCptxkN790s4ScO3cuW1O/AOBOHHqPxc6dOzVz5kzt379fCQkJmjJliho1apSj+7BYLJo1a5aWLl2qM2fOyNPTUy+88IJ69OiRR6kB3Eu1atXS5MmTlZ6ersOHD+ubb77RnDlz9PrrrysmJkaBgYHWbV1dXVWvXj1JUoMGDVS3bl09//zz8vb2vusn2reULl3aevucOnnypCwWiz766CN99NFHWW6TlJSkUqVK3ZMMDz30kHr16qVx48apcuXKmdYI3M0ff/yhI0eOqG7dulle//epWLfvvZBkfXN/a82Bq6urBgwYoPfee0/h4eF6+OGH9Z///EfPPvusfH1975jjzJkz8vPzs3kDL8m6h+ns2bM5ynEn7u7uunz58l23ueXWY/r7+9uMu7q6qnz58jpz5ky27icrDz74oM3lW2uHsrMGqGvXrtq6datatWolPz8/hYeH66mnntIjjzyS6zwAHI9DF4u0tDQFBQWpZcuW6tWrV67uY/To0dqyZYsGDhyoypUr68KFCzn6RA1AweDq6qpatWqpVq1aqlChgoYMGaLY2Ni7/m2oXbu2fH19tWbNmmwVC3vcWvTcqVMn1a9fP8ttHnrooXv6mLfOr/Hnn3/qr7/+uuub+NuZzWaFh4erS5cuWV5/a3rULUWKFMlyO4vFYv13x44dFRUVpW+++UZbtmzRRx99pE8//VRz585VtWrVspXrn2QnR1b8/f116NAhpaen58uRqTIyMrLM+vcCdcs/5Zdulq3Y2Fht2rRJmzdv1oYNG7Ro0SL17NlTr732mt2ZATgGhy4WkZGRioyMvOP16enp+uCDD7R27VpdvHhRlSpV0oABA6xTBo4fP67FixdrzZo11k+fypcvny/ZAeSdGjVqSLr5hvqfpKen6+LFi3kdyfq3xcXFJdd7PXJi8eLF+vHHH9W3b19Nnz5db7/9tj755BObbUwmU5a3feihh5SWlnbPcz700EPq1KmTOnXqpN9//13PPvusZs2apfHjx2e5fdmyZXXkyBGZzWabN90nTpyQlPkT/txq0KCBdu/erQ0bNthMu8rKrcc8ceKEzf8X6enpOn36tM33zMPDI8u9DWfPns31/zV3es0kyc3NTU2aNFGTJk2Unp6u3r17a9q0aerWrZvuu+++XD0eAMfCGou7GDFihHbv3q0PPvhAq1evVuPGjdWlSxf9/vvvkm4eCaRcuXLatGmToqKiFBUVpaFDh+qvv/4yNDeA7Nm+fXuWn+bemud+6wODtLQ0XblyJdN269ev14ULF6xFJC95e3srLCxMn3/+eZaFJ6sjPeXWqVOnrEeF6t69uwYNGqRvv/1WMTExNtsVK1Ysyze+//3vf7V7925t3rw503Wpqam6ceNGjvJcuXJF165dsxl76KGHVLx4caWnp9/xdo8//rgSEhK0bt0669iNGzc0f/58ubm5KTQ0NEc57qRt27by9fXV2LFj9dtvv2W6PikpSVOnTpUk1atXTy4uLpo/f77Nz97y5ct18eJFmw+7ypcvr19++cXmOd46q3duFStWLMsinJKSYnP51hHCLBaLrl+/nuvHA+BYHHqPxd2cPXtWK1eu1HfffWeds9y5c2dt3rxZK1euVL9+/XTq1CmdPXtWsbGxGjdunDIyMhQdHa3XXntN8+bNM/gZAPgno0aN0pUrV/TEE0/I399f169f165du/TVV1+pbNmy1qM1/fHHH+rYsaOaNGkif39/OTk5af/+/Vq9erXKli2rDh065Eved955Ry+88IKaNWum1q1bq3z58kpMTNSePXt07tw5rV69+h/v4/fff9cXX3yRadzHx0fh4eGyWCx68803VbRoUb377ruSbr5x3rBhg0aPHq26deta/yZWr15dixcv1tSpU+Xn5ycvLy/VrVtXnTt31rfffqvu3burefPmql69uq5cuaKjR49q/fr12rhxo7y8vLL9vH///Xd17NhRjRs3VmBgoIoUKaJvvvlGiYmJdz0xYZs2bfT5559r8ODBOnDggMqWLav169dr165devPNN22OCGUPDw8PTZkyRa+88oqeffZZmzNvHzx4UGvXrlVISIgkycvLS926ddPkyZPVpUsXRUVF6bffftOiRYus59m4pVWrVlq/fr26dOmi//73vzp58qTWrFlj15S36tWra926dYqOjlbNmjXl5uamqKgode7cWT4+Pqpdu7a8vb114sQJLViwQJGRkffs+wTg349icQdHjx5VRkaGGjdubDOenp6u+++/X9LNeavp6el67733VLFiRUk311y0aNFCJ06cyLQ4D0DBMnDgQMXGxur777/X559/ruvXr+vBBx+0HoDh1uLXUqVK6cknn9T27dsVExOj69evq2zZsnrxxRfVvXt3eXp65kvewMBArVixQpMnT9aqVav0119/ycvLS9WqVVPPnj2zdR8//vijde3E7cLCwhQeHq758+crLi5OkyZNsnnzP3r0aD311FMaNmyYPv30U0lSz549dfbsWc2YMUOXL19WWFiY6tatq2LFimn+/PmaPn26YmNjFRMTI3d3d1WoUEG9e/dWiRIlcvS8S5curaZNm2rbtm1avXq1ihQpIn9/f3344Yd3PXdE0aJFNX/+fI0fP16rVq3SpUuXVLFixRwd4je7Hn74Ya1Zs0YzZ87Upk2b9MUXX8jJyUn+/v565ZVX1K5dO+u2vXv3lpeXlxYsWKDo6Gh5eHiodevW6tevn81hjuvXr6/Bgwdr9uzZGjNmjGrUqKFp06bpvffey3XOF154QYcOHdLKlSs1Z84clS1bVlFRUWrTpo3WrFmj2bNnKy0tTaVLl1b79u1ztGgfAEyW7KzqcgBBQUE2R4Vat26dBgwYoLVr12ZaJOfm5iZfX199/PHHmj59ug4cOGC97urVq3r44Yc1a9YshYeH5+tzAAAAAIzCHos7qFq1qjIyMpScnGw9Fvjf1a5dWzdu3NDJkyetu6Zvrb+4V4sCAQAAgMLAoRdvX758WYcOHdKhQ4ckSadPn9ahQ4d09uxZVaxYUc2aNdPAgQO1YcMG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",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Fraction of rows with at least one S3 file: 1.0000\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAGGCAYAAADmRxfNAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA3+klEQVR4nO3deXxM9+L/8fckESSxxF7UkoSJLbaIWkrF1tp6pbZWpa6lKFeVUG77bcul0ZYq4dovrRB1bdeatlw0tFQsdaOWViqJpdWIPQjJ/P7wyPw6DTKTk5hEX8/Ho4+aM2fOeZ8RzHvO53OOyWKxWAQAAAAABrg4OwAAAACAgo9iAQAAAMAwigUAAAAAwygWAAAAAAyjWAAAAAAwjGIBAAAAwDCKBQAAAADDKBYAAAAADKNYAAAAADCMYgHgsdGvXz/169fP+vjMmTMym81au3atE1M9vv74fucls9msiIgI6+OIiAiZzWalpKQ8kv0HBwdr/Pjxj2RfAFBQuTk7AICC78SJE5ozZ47+97//KTk5WSVLlpSfn5+Cg4NtPnjOmzdP//3vf5WYmKgbN27oiSeeUOvWrTVs2DCVKlUq2/2Yzeb7Li9Tpoz27NmTa8eTndu3bysqKkqbN29WfHy80tLSVLFiRbVo0UL9+vVT9erVH1mWBzl48KD27NmjV155RcWLF892/fHjx2vdunXWxx4eHipVqpTq1Kmjzp07q3379nJxMf5dlKO5HqX8nM2ZIiIiNHv2bOtjNzc3lS9fXsHBwRo5ciTvFQArigUAQw4ePKjQ0FBVrFhRPXv2VNmyZXX+/Hl9//33+uyzz2yKxdGjR+Xv769OnTrJ09NT8fHxWrVqlXbt2qX169fLw8Mj2/21aNFCzz//vM2yIkWKSJIWL16cuwd3HykpKRo0aJCOHj2qNm3aqEuXLvLw8NDPP/+sLVu2aNWqVYqLi8vzHNk5dOiQZs+ere7du9v9wc/d3V2TJ0+WdK88nT17Vjt27NDIkSMVFBSkuXPnysvLy7p+Tt7vnOSSpCNHjsjV1dXh/TniYdmio6NlMpnydP/53XvvvScPDw/dvHlT3377rZYtW6ajR48qKirK2dEA5BMUCwCGzJs3T8WKFdPq1auzfBi7ePGizePfD2XJ1KBBA40cOVI7duxQ586ds91ftWrVshSLTO7u7g4kz5kJEybo2LFjmjVrljp27Gjz3KhRozRjxow8z5BX3Nzcsry3b7zxhhYsWKDp06fr7bff1ieffGJ9Lq/f74yMDN25c0eFCxdW4cKF83Rf2XkUP1vOdPPmTRUtWvSh63Ts2NF6ZrFPnz564403tGXLFh05ckQBAQGPIiaAfI45FgAMSUxMlJ+f332/fS5dunS2r69UqZIk6erVq4az2Dvm/9SpU9Zv4evVq6eQkBBt374929d9//332rlzp3r06JGlVEj3Pny++eabNsu+/fZbvfTSS2rQoIECAwM1bNgwnTp1ymad8ePHKzg4OMv2MucR/J7ZbNakSZO0bds2denSRXXr1lXnzp319ddf27zuww8/lCS1bdtWZrNZZrNZZ86cyfYY7+fVV19Vy5YtFR0drZ9//tm6/H7v97Jly9S5c2fVr19fTZo0UUhIiDZu3GhXrsxj27Bhgzp37qx69eopJibG+tz9iumlS5f0+uuvq1GjRmratKkmT56s27dvW59/2Dyb328zu2z3m2ORlJRk/TmqX7++evXqpZ07d9qss2/fPpnNZm3ZskVz585Vq1atVK9ePb3yyitKSEjI5p3//z8Dp06deuhxZvrPf/6jkJAQBQQEKCgoSG+88YbOnz9vs06/fv3UpUsXxcXFqW/fvqpfv74+/vjjbLP8UWBgoKR7fwf83tatW60ZmjZtqrCwMP3666/W57dv3y6z2azjx49bl33xxRcym80aMWKEzbaee+45jRo1yuFsAJyDMxYADKlUqZIOHTqkkydPqmbNmtmub7FYdOnSJaWnpyshIUHTpk2Tq6urgoKC7Nrf7du3s0zY9fLysvsb5R9//FEvvviiypcvr8GDB8vDw0Nbt27V8OHDFRERofbt2z/wtf/9738l6YFnTP7om2++0eDBg1W5cmWNGDFCt27dUmRkpF588UWtXbtWlStXtms7f3TgwAF9+eWXeumll+Tp6ally5ZZz/p4e3urffv2On36tDZt2qQJEybI29tbkuyax/Ig3bp10+7du/XNN988cA7JqlWrNHnyZHXs2FGhoaG6ffu2Tpw4oe+//15du3a1K9fevXu1detW9e3bV97e3tbi+SCjRo1SpUqVNGbMGB0+fFjLli3T1atXrSXBXo6+Z8nJyerTp49u3rypfv36ydvbW+vWrdOwYcM0a9asLD9HCxculMlk0oABA3T9+nUt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tS9evKgyZco4KRUAAAAARzm1WLi7u6tOnTr69ttvrcsyMjL07bffqmHDhk5MBgAAAMARTh8K9de//lVvvvmm6tatq4CAAH366ae6efOmQkJCnB0NAAAAgJ2cXiw6deqklJQUzZo1S7/99ptq1aqlRYsWMRQKAAAAKEBMFovF4uwQAAAAAAo2rmMJAAAAwDCKBQAAAADDKBYAAAAADKNYAAAAADCMYgEAAADAMIoFAAAAAMMoFgAApzl//rwmTJjg7BgAgFxAsQAAOM2VK1e0fv16Z8cAAOQCp995GwDw+Nq+fftDn09KSnpESQAAeY07bwMA8oy/v79MJpMe9k+NyWTSsWPHHmEqAEBe4IwFACDPlC1bVu+++67atWt33+ePHTumkJCQR5wKAJAXmGMBAMgzderU0dGjRx/4fHZnMwAABQdDoQAAeSY2Nlapqalq1arVfZ9PTU1VXFycgoKCHnEyAEBuo1gAAAAAMIyhUAAAAAAMo1gAAAAAMIxiAQAAAMAwigUAAAAAwygWAPAnc+bMGZnN5nx1U7pTp06pV69eqlevnp5//nlnx7EKDg7W0qVLrY/NZrO2bdvmvEAAkI9xgzwAeMTGjx+vdevWacyYMXr11Vety7dt26bhw4frxIkTTkznHBERESpatKiio6Pl4eFx33VSUlI0c+ZM7dq1S8nJySpRooT8/f312muvqXHjxpKkd955R998840uXLggDw8PNWzYUGFhYfL19X3gvvv166fvvvsuy/KjR49q9erVKlq0aO4cJAA85igWAOAEhQsX1sKFC9W7d2+VKFHC2XFyRVpamtzd3XP02sTERD3zzDOqVKnSA9f529/+pjt37mjq1Kl68skndfHiRX377be6fPmydZ06deqoa9eueuKJJ3TlyhVFRERo4MCB2r59u1xdXR+47V69emnkyJE2y9zc3FSqVKkcHQ8A/BkxFAoAnKB58+YqU6aM5s+f/8B1IiIisgwLWrp0qYKDg62Px48fr9dee03z5s1T8+bNFRgYqNmzZ+vu3bv64IMPFBQUpFatWmnNmjVZth8fH68+ffqoXr166tKlS5Zv7U+ePKlBgwapYcOGat68ucaOHauUlBTr8/369dOkSZM0ZcoUNW3aVAMHDrzvcWRkZGj27Nlq1aqV6tatq+eff15ff/219Xmz2ayjR49qzpw5MpvNioiIyLKNq1evKjY2VmFhYXrqqadUqVIlBQQEaMiQIWrbtq11vd69e6tJkyaqXLmy6tSpo1GjRun8+fM6e/bsA99nSSpSpIjKli1r85+UdSjUH50/f16vv/66AgMDFRQUpGHDhunMmTPW5/ft26cePXqoQYMGCgwMVJ8+fbLNAgAFFcUCAJzAxcVFo0ePVmRkpH755RdD29q7d68uXLigyMhIjR8/XhERERoyZIhKlCihVatWqU+fPnr33Xez7OfDDz/UX//6V61fv14NGjTQ0KFDdenSJUn3Psi/8sorql27tlavXq1Fixbp4sWLGjVqlM021q1bp0KFCikqKkoTJ068b77PPvtMS5Ys0ZtvvqkNGzaoZcuWeu2113T69GlJ0u7du1WjRg0NGDBAu3fv1oABA7Jsw8PDQx4eHtq2bZvS0tLsel9SU1O1du1aVa5cWRUqVLDrNY64c+eOBg4cKE9PTy1fvlxRUVHy8PDQoEGDlJaWprt372r48OFq0qSJNmzYoM8//1y9e/eWyWTK9SwAkB9QLADASdq3b69atWpp1qxZhrZTsmRJvf322/Lx8VGPHj1UvXp13bp1S0OHDlW1atU0ZMgQFSpUSAcOHLB5Xd++fdWxY0f5+vrqvffeU7FixbR69WpJUmRkpGrXrq3Ro0fL19dXtWvX1vvvv699+/bp559/tm6jWrVqGjdunHx8fOTj43PffIsXL9bgwYPVuXNn+fj4aOzYsfL399enn34qSSpbtqxcXV3l4eGhsmXLytPTM8s23NzcNHXqVK1fv976zf/HH3+s48ePZ1l3+fLlatiwoRo2bKivv/5aS5YsyXaIVlRUlPU1DRs21NSpUx/+pkvasmWLMjIyNGXKFJnNZvn6+io8PFznz5/Xd999p+vXr+vatWtq06aNqlSpIl9fX3Xv3l0VK1bMdtsAUBAxxwIAnCgsLEyvvPLKA4cR2cPPz08uLv//e6IyZcqoRo0a1seurq4qWbKkLl68aPO6hg0bWn/t5uamunXrKj4+XpJ0/Phx7du3z2adTImJiapevbqke3MaHub69eu6cOGCGjVqZLO8UaNG9y0FD9OxY0c988wzio2N1eHDhxUTE6NFixZp8uTJCgkJsa7XrVs3tWjRQr/99psWL16sUaNGKSoqSoULF37gtrt27aqhQ4daHxcrVizbPMePH1diYmKWY7t9+7YSExPVsmVLhYSEaODAgWrRooWaNWum5557TuXKlXPouAGgoKBYAIATNWnSRC1bttT06dNtPhxLkslkksVisVl29+7dLNtwc7P9q9xkMt13WUZGht25UlNT1aZNG4WFhWV5LnP+gaRHfsWkwoULq0WLFmrRooWGDx+ut956SxERETbvXbFixVSsWDFVq1ZN9evXV1BQkL766it16dLlgdv18vJS1apVHcqSmpqqOnXqaNq0aVmey5z0HR4ern79+ikmJkZbt27VJ598oiVLlqhBgwYO7QsACgKGQgGAk40ZM0Y7duzQoUOHbJaXKlVKycnJNuUiN+89cfjwYeuv7969q6NHj1qHM9WpU0c//vijKlWqpKpVq9r896DLwd6Pl5eXypUrp4MHD9osP3jwoPz8/Awfg5+fn1JTUx+6jsVisXtehiPq1KmjhIQElS5dOst79PszHrVr19aQIUO0cuVK1axZU5s2bcr1LACQH1AsAMDJzGazunbtqmXLltksb9q0qVJSUrRw4UIlJiZq+fLliomJybX9rlixQl999ZVOnTqlSZMm6cqVK3rhhRckSS+99JKuXLmi0aNH68iRI0pMTFRMTIwmTJig9PR0h/YzcOBALVy4UFu2bFF8fLymTZum48ePKzQ01O5tXLp0SaGhofrPf/6j48ePKykpSVu3btWiRYusV4VKSkrS/PnzFRcXp3PnzungwYMaOXKkihQpotatWzuU2R5du3aVt7e3hg0bptjYWCUlJWnfvn2aPHmyfvnlFyUlJWn69Ok6dOiQzp49q927d+v06dMPnIsCAAUdQ6EAIB8YOXKktmzZYrPM19dX7777rubPn6+5c+eqQ4cOGjBggFatWpUr+xwzZowWLFigY8eOqWrVqpo7d651CE/58uUVFRWladOmaeDAgUpLS1PFihX19NNP28znsEdoaKiuX7+uqVOnKiUlRb6+vvrnP/+patWq2b0NT09P1a9fX59++qkSExN19+5dVahQQT179rTOjXB3d1dsbKw+/fRTXb16VaVLl1ZgYKCioqJUunRphzLbo2jRooqMjNS0adM0YsQI3bhxQ+XLl1ezZs3k5eWlW7duKT4+XuvWrdPly5dVrlw59e3bV3369Mn1LACQH5gsfxzACwAAAAAOYigUAAAAAMMoFgAAAAAMo1gAAAAAMIxiAQAAAMAwigUAAAAAwygWAAAAAAyjWAAAAAAwjGIBAAAAwDCKBQAAAADDKBYAAAAADKNYAAAAADCMYgEAAADAsP8H4V9C/DgZmFQAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Duration stats (seconds):\n",
      "count    5.582625e+06\n",
      "mean     1.335804e+02\n",
      "std      9.245260e+01\n",
      "min      3.000002e+01\n",
      "25%      6.000000e+01\n",
      "50%      9.989224e+01\n",
      "75%      2.002024e+02\n",
      "max      4.808160e+02\n",
      "Name: duration, dtype: float64\n"
     ]
    },
    {
     "data": {
      "image/png": "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QECAQkJCNHbsWON8JycntWzZUmvXrn3g+wMABQGhAgDs0OOPP646derohx9+sHjdSZMmaejQoVq3bp38/f2Vlpam0NBQff3111q5cqVatGih/v376+zZs5Kk6dOnq3z58nrzzTe1fft2bd++Pdvtbtq0SePHj1evXr0UExOjF154Qe+9955++eUXk+VmzJihp59+WqtXr1bLli01bNgwXb58+b717t27VwEBASbTPvroI2VkZGjRokWKiYnRsGHD5O7uLulOmHr55ZdVr149LV++XF9++aWSkpI0ePBgk/dgzpw5ev3117Vu3Tp98skn8vX1lSSlpaWpT58+8vLy0vLlyzVlyhTt3LlTY8aMMalh165dOnXqlObPn68JEyZo5cqVxpAn3QkeiYmJWrBggaZNm6YlS5YoKSnJOH/jxo36+uuvFRUVpR9++EGff/65ateubbKPwMBA/frrr/d9bwCgoHC2dQEAgOxVr15dhw8ftni9N998U8HBwcbXpUqVUp06dYyvBw8erM2bN2vLli2KjIxUqVKl5OTkpBIlSqhMmTL33e5XX32lsLAwRURESJKqVaumffv2ae7cuXrssceMy4WFhalTp06SpLffflsLFy7U/v371bJly2y3e/bs2Syh4uzZs3rqqaeMd00qV65snLdo0SLVq1dPb7/9tnHa+PHjFRoaquPHj6tMmTJasGCBRo8erbCwMElSlSpVjHdd1qxZo4yMDE2cONEYVEaPHq3+/ftr2LBhxvDh5eWl0aNHy8nJSTVq1FBoaKhiY2PVrVs3HT9+XD///LO+++47BQYGSpLGjRunDh06GGtKTEyUr6+vgoKCVKxYMVWsWNG47F1ly5ZVYmKiMjMz5ejI93wACi5CBQDYKYPBIAcHB4vXa9Cggcnr1NRUzZgxQ1u3btWFCxd0+/ZtpaenG+9UmOvYsWPq3r27ybQmTZpowYIFJtPuBgFJcnd3l4eHh0nTpL9LT0+Xq6urybSePXvqww8/1Pbt2xUUFKR27doZg9GhQ4e0a9cuNW7cOMu2Tp06patXryojI8Mk6Nzrzz//lL+/vzFQ3D2OzMxMHT9+3BgqatasKScnJ+MyZcqU0ZEjR4zbcHZ2NglDNWrUUMmSJY2v27dvr/nz56tNmzZq0aKFQkND1apVKzk7/9//et3c3JSZmamMjAy5ubnd9z0CAHtHqAAAO/Xnn3+qUqVKkmT8FttgMBjn368TdvHixU1eT5w4UTt37tTw4cNVpUoVubm56c033zTpH5CbihUrZvLawcHhgSMclS5dWikpKSbTunbtqpCQEG3dulU7duzQ7NmzNXz4cPXo0UNpaWlq1aqVhg0blmVbZcqU0enTp3PlOO69+L97HPe+/w9ToUIFbdiwQTt37tTOnTsVFRWlr776SgsXLjS+R1euXJG7uzuBAkCBx71WALBDsbGxOnLkiNq1aydJ8vb2liRduHDBuMy9nbYfJC4uTmFhYWrbtq38/f3l6+urM2fOmCxTrFixhw5tWr16df33v/81mfbf//5XNWvWNKuO+6lXr56OHj2aZXqFChX04osvasaMGerVq5eWLVsmSapfv77i4+Pl5+enqlWrmvy4u7vrkUcekZubW5a+HnfVqFFDhw8fVlpamslxODo6qlq1ambVXL16dd26dUsHDhwwTjt27FiWcOTm5qbWrVtr1KhRWrBggeLi4ox3O6Q7Hc7r1q1r1j4BwJ4RKgDAxjIyMnThwgWdO3dOv//+u2bNmqXXX39drVq10nPPPSfpzsVpo0aNNHv2bP3555/avXu3pkyZYtb2q1atqk2bNungwYM6dOiQhg4dmiVA+Pn5ac+ePTp37tx9myq9+uqrWrlypZYsWaITJ05o3rx52rRpk3r37m3N4SskJET79u3T7du3jdPGjRunbdu26fTp0/r999+1a9cu1ahRQ5L00ksv6cqVK3r77be1f/9+nTp1Stu2bdPIkSN1+/Ztubq6qm/fvvr444+1atUqnTp1Svv27dN3330nSXrmmWfk4uKiESNG6MiRI/rll180ZswYde7c2dj06WGqV6+uFi1a6IMPPtBvv/2mAwcOaNSoUSZ3HFasWKHvvvtOR44c0enTp7V69Wq5ubmpYsWKxmV+/fVXk/4vAFBQ0fwJAGxs27ZtCgkJkbOzs0qWLKk6depo1KhRCgsLM+m8O378eP3zn/9Uly5dVK1aNb3zzjtmXdCPGDFC7733nl544QWVLl1affv2NRk+VbrTuXv06NFq06aNMjIysu0g3qZNG7333nuaO3euxo8fLz8/P40fP17Nmze36vhbtmwpJycn7dy5Uy1atJB0Z0jYjz76SH/99Zc8PDzUokULjRw5UpJUrlw5ffPNN/rkk0/Up08fZWRkqGLFimrRooXx/Xr99dfl5OSkadOm6fz58ypTpoxeeOEFSXeah3311VcaN26cnn/+eRUvXlzt2rXTiBEjLKo7Ojpao0aNUmRkpHx9ffXWW29p2rRpxvklS5bU7NmzNWHCBGVmZqp27dqaNWuWSpcuLUk6d+6c4uLi9PHHH1v1/gGAPXAwWNJAFACAPLB48WJt2bJFX331la1LyTcff/yxUlJSsgxlCwAFEXcqAAA21717d6WkpOjatWvy8PCwdTn5wsfHR7169bJ1GQCQK7hTAQAAAMAqdNQGAAAAYBVCBQAAAACrECoAAAAAWIVQAQAAAMAqhAoAAAAAViFUAAAAALAKoQIAAACAVQgVAAAAAKxCqAAAAABgFUIFAAAAAKv8P4R/7EzAaxeiAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "# --- S3 file extension value counts and fractions ---\n",
    "# Flatten the list of s3_files to get all extensions\n",
    "all_extensions: list[str] = [ext for exts in user_upload_df[\"s3_files\"] for ext in exts]\n",
    "ext_counts: pd.Series = pd.Series(all_extensions).value_counts()\n",
    "ext_fractions: pd.Series = ext_counts / ext_counts.sum()\n",
    "\n",
    "print(\"S3 file extension counts:\")\n",
    "print(ext_counts)\n",
    "print(\"\\nS3 file extension fractions:\")\n",
    "print(ext_fractions)\n",
    "\n",
    "# --- Plot S3 file extension distribution ---\n",
    "plt.figure(figsize=(8, 4))\n",
    "ext_counts.plot(kind=\"bar\")\n",
    "plt.title(\"S3 File Extension Counts\")\n",
    "plt.xlabel(\"Extension\")\n",
    "plt.ylabel(\"Count\")\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# --- S3 existence fraction ---\n",
    "s3_exists_fraction: float = user_upload_df[\"s3_exists\"].mean()\n",
    "print(f\"\\nFraction of rows with at least one S3 file: {s3_exists_fraction:.4f}\")\n",
    "\n",
    "# --- S3 file count distribution ---\n",
    "plt.figure(figsize=(8, 4))\n",
    "user_upload_df[\"s3_file_count\"].value_counts().sort_index().plot(kind=\"bar\")\n",
    "plt.title(\"S3 File Count Distribution per Row\")\n",
    "plt.xlabel(\"Number of S3 Files\")\n",
    "plt.ylabel(\"Number of Rows\")\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "# --- Duration distribution analysis ---\n",
    "durations: pd.Series = user_upload_df[\"duration\"].dropna()\n",
    "print(f\"\\nDuration stats (seconds):\\n{durations.describe()}\")\n",
    "\n",
    "plt.figure(figsize=(8, 4))\n",
    "plt.hist(durations, bins=50, color=\"skyblue\", edgecolor=\"black\", log=True)\n",
    "plt.title(\"Audio Duration Distribution (log scale)\")\n",
    "plt.xlabel(\"Duration (seconds)\")\n",
    "plt.ylabel(\"Count (log scale)\")\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f677898c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# user_upload_df.to_pickle(\"/home/tony/Data/user_upload_df_20250601_to_20250820.pkl\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f584be4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "suno_env_dev",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
