{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# \ud83c\udf99\ufe0f Maya 2 Native TTS on Tesla T4 GPU + Cloudflare Tunnel\n",
    "\n",
    "This notebook hosts **`maya-research/maya2-native`** (multilingual TTS model supporting 12 languages and 20 native voice personas) on **Google Colab / Kaggle T4 GPU** and exposes an **OpenAI-compatible speech endpoint** via a free **Cloudflare Quick Tunnel**.\n",
    "\n",
    "### \u26a1 Quick Steps:\n",
    "1. Go to **Runtime -> Change runtime type -> Hardware accelerator -> T4 GPU**.\n",
    "2. (Optional) Paste your **Dashboard URL** and **Session ID** from your Vercel Dashboard below.\n",
    "3. Click **Runtime -> Run all**.\n",
    "4. Copy the generated `trycloudflare.com` URL (or watch the dashboard auto-connect)!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#@title 1. Check GPU\n",
    "!nvidia-smi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#@title 2. Configuration (Auto-sync with Vercel Dashboard)\n",
    "#@markdown Enter the session details from your Vercel web app to connect automatically:\n",
    "DASHBOARD_URL = \"\" #@param {type:\"string\"}\n",
    "SESSION_ID = \"\" #@param {type:\"string\"}\n",
    "\n",
    "print(f\"Configured Dashboard: {DASHBOARD_URL or 'None (Manual tunnel URL paste)'}\")\n",
    "print(f\"Session ID: {SESSION_ID or 'None'}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#@title 3. Install Dependencies\n",
    "# 1. Critical: Remove incompatible torchvision to prevent MimiModel crash\n",
    "!pip uninstall -y torchvision\n",
    "# 2. Install PyTorch with CUDA 12.8 wheel and Maya3 package\n",
    "!pip install --upgrade pip\n",
    "!pip install \"maya3[server] @ git+https://github.com/MayaResearch/maya2-native\" --extra-index-url https://download.pytorch.org/whl/cu128\n",
    "!pip install fastapi uvicorn soundfile numpy requests python-multipart\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#@title 4. Write Maya 2 Native Server Script\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#@title 5. Download Cloudflared & Launch Tunnel\n",
    "import subprocess, urllib.request, os, re, json, time, threading\n",
    "\n",
    "# Download cloudflared\n",
    "if not os.path.exists(\"./cloudflared\"):\n",
    "    print(\"Downloading cloudflared...\")\n",
    "    urllib.request.urlretrieve(\n",
    "        \"https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64\",\n",
    "        \"./cloudflared\"\n",
    "    )\n",
    "    os.chmod(\"./cloudflared\", 0o777)\n",
    "\n",
    "# Start FastAPI server in background\n",
    "print(\"Starting FastAPI server on port 8000...\")\n",
    "server_p = subprocess.Popen([\"uvicorn\", \"server:app\", \"--host\", \"0.0.0.0\", \"--port\", \"8000\"])\n",
    "time.sleep(3)\n",
    "\n",
    "# Start Cloudflare quick tunnel\n",
    "print(\"Establishing Cloudflare Quick Tunnel...\")\n",
    "cf_p = subprocess.Popen([\"./cloudflared\", \"tunnel\", \"--url\", \"http://127.0.0.1:8000\", \"--no-autoupdate\"], \n",
    "                        stderr=subprocess.PIPE, text=True)\n",
    "\n",
    "tunnel_url = None\n",
    "pattern = re.compile(r\"https://[a-zA-Z0-9-]+\\.trycloudflare\\.com\")\n",
    "for line in iter(cf_p.stderr.readline, ''):\n",
    "    match = pattern.search(line)\n",
    "    if match:\n",
    "        tunnel_url = match.group(0)\n",
    "        break\n",
    "\n",
    "print(\"\\n\" + \"=\"*75)\n",
    "print(f\"\ud83c\udf89 SUCCESS! CLOUDFLARE TUNNEL IS ONLINE:\")\n",
    "print(f\"\ud83d\udc49 {tunnel_url}\")\n",
    "print(f\"API: {tunnel_url}/v1/audio/speech\")\n",
    "print(\"=\"*75 + \"\\n\")\n",
    "\n",
    "# Broadcast to ntfy.sh relay for instant auto-connect across localhost/clouds\n",
    "if SESSION_ID and tunnel_url:\n",
    "    try:\n",
    "        urllib.request.urlopen(urllib.request.Request(f\"https://ntfy.sh/maya2-{SESSION_ID}\", data=tunnel_url.encode(\"utf-8\")), timeout=5)\n",
    "        print(\"\u2713 Broadcasted tunnel URL to Dashboard relay!\")\n",
    "    except Exception:\n",
    "        pass\n",
    "\n",
    "# If Dashboard Webhook is configured, send tunnel URL automatically\n",
    "if DASHBOARD_URL and SESSION_ID and tunnel_url:\n",
    "    webhook_url = DASHBOARD_URL.rstrip(\"/\") + \"/api/tunnel/register\"\n",
    "    print(f\"Registering tunnel URL with Dashboard: {webhook_url}...\")\n",
    "    try:\n",
    "        req = urllib.request.Request(\n",
    "            webhook_url,\n",
    "            data=json.dumps({\"sessionId\": SESSION_ID, \"tunnelUrl\": tunnel_url, \"status\": \"online\"}).encode(\"utf-8\"),\n",
    "            headers={\"Content-Type\": \"application/json\"}\n",
    "        )\n",
    "        urllib.request.urlopen(req, timeout=5)\n",
    "        print(\"\u2713 Auto-connected to Vercel Dashboard!\")\n",
    "    except Exception as e:\n",
    "        print(f\"Webhook notice: {e}\")\n",
    "\n",
    "# Keep cell running\n",
    "try:\n",
    "    cf_p.wait()\n",
    "except KeyboardInterrupt:\n",
    "    print(\"Stopping...\")\n",
    "    cf_p.terminate()\n",
    "    server_p.terminate()"
   ]
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "gpuType": "T4",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "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.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}