{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "# 程式特色\n",
        "*   使用edge-tts\n",
        "*   使用gradio\n",
        "*   佈署到cloud run\n",
        "*   產生的聲音可以下載\n",
        "*   用在國三技藝班或群科"
      ],
      "metadata": {
        "id": "S4Ov6p9lKD21"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "區塊 1：安裝環境與套件：\n",
        "\n",
        "我們的雲端電腦預設沒有「微軟語音套件」和「網頁介面工具」。我們要下達系統指令（開頭加上 !），把 edge-tts（負責發聲）和 gradio（負責畫網頁）安裝進來。"
      ],
      "metadata": {
        "id": "zWHsRxB8h5Zp"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 安裝必要的套件 (-q 代表安靜模式，讓安裝畫面乾淨一點)\n",
        "!pip install edge-tts gradio -q\n",
        "\n",
        "print(\"✅ 步驟 1 完成：語音與網頁套件安裝完畢！\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "dQ9lhp9Lh39z",
        "outputId": "8763c1f5-8e61-48d4-8765-124d66f759bc"
      },
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ 步驟 1 完成：語音與網頁套件安裝完畢！\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "區塊 2：匯入所需模組：\n",
        "\n",
        "安裝好套件後，我們要用 import 指令把它們「拿出來」放到桌面上準備使用。除了語音和網頁工具，我們還需要 tempfile 來產生暫存的 MP3 檔案，以及 asyncio 來處理需要等待網路傳輸的任務。"
      ],
      "metadata": {
        "id": "uGKgF7IgiD1g"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import gradio as gr\n",
        "import edge_tts\n",
        "import tempfile\n",
        "import asyncio\n",
        "\n",
        "print(\"✅ 步驟 2 完成：所有工具都已匯入，準備開始寫程式！\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "x3RTPL2yiKlh",
        "outputId": "8bfb390e-9a39-4022-9a54-34014d8f4b87"
      },
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ 步驟 2 完成：所有工具都已匯入，準備開始寫程式！\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "區塊 3：打造 AI 核心邏輯 (後端大腦)\n",
        "\n",
        "接下來我們要寫一個「大腦函式」。它的工作很單純：接收我們輸入的「文字」和「聲音選項」，然後請微軟 AI 幫我們唸出來，最後存成一個 MP3 檔案交還給我們。"
      ],
      "metadata": {
        "id": "2DpI3U90iPog"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 定義產生語音的非同步函式 (async 代表這是一個允許等待的任務)\n",
        "async def generate_speech(text, voice_choice):\n",
        "    # 如果沒有輸入文字，就直接停止\n",
        "    if not text.strip():\n",
        "        return None\n",
        "\n",
        "    # 根據使用者的選擇，設定對應的微軟語音模型\n",
        "    if voice_choice == \"男聲 (台灣 - 雲哲)\":\n",
        "        voice = \"zh-TW-YunJheNeural\"\n",
        "    else:\n",
        "        voice = \"zh-TW-HsiaoChenNeural\" # 台灣女聲 - 曉臻\n",
        "\n",
        "    # 建立一個暫存檔案來儲存生成的 MP3\n",
        "    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=\".mp3\")\n",
        "    output_path = temp_file.name\n",
        "\n",
        "    # 呼叫 edge-tts 進行文字轉語音\n",
        "    communicate = edge_tts.Communicate(text, voice)\n",
        "    await communicate.save(output_path) # await 代表等待 AI 處理完畢並存檔\n",
        "\n",
        "    # 回傳檔案路徑，之後會交給網頁介面播放\n",
        "    return output_path\n",
        "\n",
        "print(\"✅ 步驟 3 完成：AI 核心邏輯已經建立！\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Pdo256ntiSCA",
        "outputId": "8c9b247e-f547-41d4-bc95-4c2c4c2e5e31"
      },
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ 步驟 3 完成：AI 核心邏輯已經建立！\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "區塊 4：設計網頁介面並啟動 (前端畫面)"
      ],
      "metadata": {
        "id": "nEs8XIEwiWNR"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# 建立漂亮的 Gradio 網頁介面 (使用柔和主題)\n",
        "with gr.Blocks(theme=gr.themes.Soft()) as demo:\n",
        "    gr.Markdown(\n",
        "        \"\"\"\n",
        "        # 🗣️ 智光商工 電機電子群 AI 雲端語音合成器\n",
        "        請在左方輸入您想要轉換的文字，並選擇聲音，AI 會立刻為您生成專屬語音！\n",
        "        \"\"\"\n",
        "    )\n",
        "\n",
        "    with gr.Row():\n",
        "        # 左側區塊：使用者輸入區\n",
        "        with gr.Column():\n",
        "            text_input = gr.Textbox(\n",
        "                label=\"📝 請輸入文字\",\n",
        "                placeholder=\"例如：媽媽我愛你，母親節快樂！\",\n",
        "                lines=5\n",
        "            )\n",
        "            voice_input = gr.Radio(\n",
        "                choices=[\"女聲 (台灣 - 曉臻)\", \"男聲 (台灣 - 雲哲)\"],\n",
        "                value=\"女聲 (台灣 - 曉臻)\",\n",
        "                label=\"🎤 請選擇聲音\"\n",
        "            )\n",
        "            submit_btn = gr.Button(\"✨ 產生語音\", variant=\"primary\")\n",
        "\n",
        "        # 右側區塊：播放與結果區\n",
        "        with gr.Column():\n",
        "            audio_output = gr.Audio(label=\"🎧 語音輸出結果\", type=\"filepath\")\n",
        "\n",
        "    # 設定按鈕點擊後的動作：把輸入的資料交給剛剛寫好的 generate_speech 函式，並把結果傳給 audio_output\n",
        "    submit_btn.click(\n",
        "        fn=generate_speech,\n",
        "        inputs=[text_input, voice_input],\n",
        "        outputs=audio_output\n",
        "    )\n",
        "\n",
        "# 啟動介面！share=True 會產生一組 72 小時有效的公開網址\n",
        "print(\"✅ 步驟 4 完成：正在啟動網頁介面...\")\n",
        "demo.launch(share=True, debug=False)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 663
        },
        "id": "-ysHpYk4iZ9A",
        "outputId": "2eb071a5-b61a-435a-a4e7-7582f94d6e5d"
      },
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "/tmp/ipykernel_1767/2792204342.py:2: DeprecationWarning: The 'theme' parameter in the Blocks constructor will be removed in Gradio 6.0. You will need to pass 'theme' to Blocks.launch() instead.\n",
            "  with gr.Blocks(theme=gr.themes.Soft()) as demo:\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ 步驟 4 完成：正在啟動網頁介面...\n",
            "Colab notebook detected. To show errors in colab notebook, set debug=True in launch()\n",
            "* Running on public URL: https://d861468ba7f5d556e1.gradio.live\n",
            "\n",
            "This share link expires in 1 week. For free permanent hosting and GPU upgrades, run `gradio deploy` from the terminal in the working directory to deploy to Hugging Face Spaces (https://huggingface.co/spaces)\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ],
            "text/html": [
              "<div><iframe src=\"https://d861468ba7f5d556e1.gradio.live\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": []
          },
          "metadata": {},
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [],
      "metadata": {
        "id": "V3eHKWYSh0l5"
      }
    }
  ]
}