返回目錄
A
從零到偶像:生成式 AI 與虛擬人物的跨域實踐 - 第 7 章
第 7 章:內容創作工作流與自動化
發布於 2026-03-02 22:27
# 第 7 章 內容創作工作流與自動化
在本章中,我們將把前面幾章所建構的 **角色定位、視覺形象、聲音人格** 具體落實到 **日常內容產出與即時互動** 的完整工作流。讀者將學會如何使用生成式 AI 自動撰寫腳本、即時回應粉絲訊息,並將這些素材無縫串接至 **Discord / Telegram 機器人** 以及 **OBS** 直播系統,達成「全自動」的虛擬偶像運營管線。
---
## 7.1 內容創作全景圖
```mermaid
graph LR
A[概念腳本] --> B[文本生成 LLM]
B --> C[情感標記 & SSML]
C --> D[語音 TTS / 歌曲 DiffSinger]
D --> E[多媒體合成 (VFX + 2D/3D) ]
E --> F[OBS Live Output]
F --> G[觀眾互動 (Discord/Telegram Bot)]
G --> H[即時回應生成]
H --> B
```
如上圖所示,**內容創作循環** 包含三大環節:
1. **腳本生成** – 以大型語言模型 (LLM) 產出劇本、直播腳本或短視頻文案。
2. **多模態合成** – 文本 → SSML → TTS/歌聲 → 視覺渲染 → OBS 輸出。
3. **即時互動** – 機器人捕捉粉絲訊息 → 情感分析 → 生成回覆 → TTS 回放。
本章將針對每個環節提供 **工具選型、實作步驟、最佳實踐**,並示範完整的 **自動化 pipeline**。
---
## 7.2 腳本生成:從概念到文本
### 7.2.1 為什麼使用 LLM?
- **多樣性**:同一主題可快速生成多種敘事風格。
- **可控性**:透過 **Prompt Engineering**、**Few‑Shot** 範例與 **Function Calling**(如 OpenAI function calling)可限制輸出格式。
- **成本效益**:使用 **Open‑Source**(如 Llama‑3、Mistral)或 **雲端服務**(OpenAI GPT‑4o、Claude 3.5)依需求切換。
### 7.2.2 Prompt 基礎模板
```text
[角色設定]
- 姓名:{{name}}
- 年齡:{{age}}
- 人格特徵:{{personality}}
- 語氣:{{tone}}
[任務描述]
請以 {{tone}} 的語氣,為 {{event}} 撰寫一段 150~200 字的直播開場白,內容需包含以下三個要點:
1. 歡迎新粉絲
2. 簡短介紹本次活動主題
3. 呼籲觀眾在聊天室互動
[回覆格式]
{{
"script": "...",
"keywords": ["...","..."]
}}
```
> **Tip**:將 `{{keywords}}` 作為後續情感控制或字幕自動生成的依據。
### 7.2.3 使用 Python 呼叫 OpenAI API(示例)
```python
import openai, json, os
def generate_script(prompt: str, model: str = "gpt-4o-mini") -> dict:
response = openai.ChatCompletion.create(
model=model,
messages=[{"role": "system", "content": "You are a creative assistant for a virtual idol."},
{"role": "user", "content": prompt}],
temperature=0.7,
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
# 範例 Prompt
prompt = """[角色設定]\n- 姓名:星瀾\n- 年齡:18\n- 人格特徵:活潑、好奇、帶點神祕感\n- 語氣:甜美且帶有輕微的電子音效\n\n[任務描述]\n請以甜美的語氣,為即將舉行的《星光音樂會》撰寫一段 180 字的直播開場白,內容需包含以下三個要點:\n1. 歡迎新粉絲\n2. 簡短介紹本次活動主題\n3. 呼籲觀眾在聊天室互動\n\n[回覆格式]\n{{\n "script": "...",\n "keywords": ["...","..."]\n}}"""
result = generate_script(prompt)
print(result["script"])
```
---
## 7.3 多模態合成:文本 → SSML → TTS / 歌聲
### 7.3.1 SSML 與情感標記
**SSML(Speech Synthesis Markup Language)** 能夠在文字中嵌入語速、音高、情緒等指令,讓 TTS 輸出更貼合角色設定。以下是一段範例:
```xml
<speak version="1.0" xmlns="https://www.w3.org/2001/10/synthesis" xml:lang="zh-TW">
<prosody rate="+10%" pitch="+5%">
大家好,我是 <emphasis level="moderate">星瀾</emphasis>!
</prosody>
<break time="500ms"/>
<prosody rate="-5%" pitch="-3%" volume="soft">
今晚,我們將一起踏上星光之旅…
</prosody>
</speak>
```
> **技巧**:將腳本中的 **關鍵字**(如 `{{emotion}}`)映射為 SSML `<prosody>` 參數,實現 **情感可編程**。
### 7.3.2 TTS 引擎選型
| 類型 | 代表模型 | 開源/商用 | 特色 | 適合情境 |
|------|----------|----------|------|----------|
| 神經網路 TTS | **VITS**、**FastSpeech 2** | 開源 | 高品質、可自訂聲線 | 角色說話、劇本朗讀 |
| 商業雲端 | **Azure Neural Speech**、**Google WaveNet**、**OpenAI Text-to-Speech (TTS‑o1)** | 商用 | 多語言、情感參數化 | 需要 SLA、低延遲直播 |
| 歌聲合成 | **DiffSinger**、**so‑vits‑svc** | 開源 | 音高與音色分離、可轉換風格 | 虛擬歌手演唱 |
> **實務建議**:將 **VITS LoRA** 微調後作為主力 TTS,備援使用 **Azure** 以確保高可用性。
### 7.3.3 端到端合成腳本(Python)
```python
import json, subprocess
from pathlib import Path
# 1. 讀取 LLM 產出的腳本與關鍵字
with open("script.json", "r", encoding="utf-8") as f:
data = json.load(f)
script = data["script"]
keywords = data["keywords"]
# 2. 依關鍵字插入情感 SSML(簡易映射)
emotion_map = {
"歡迎": "<prosody rate='+5%'>",
"驚喜": "<prosody pitch='+10%'>",
"柔和": "<prosody volume='soft'>"
}
ssml_body = script
for kw in keywords:
if kw in emotion_map:
ssml_body = f"{emotion_map[kw]}{ssml_body}</prosody>"
ssml = f"<speak>{ssml_body}</speak>"
Path("output.ssml").write_text(ssml, encoding="utf-8")
# 3. 呼叫本地 VITS(假設使用 vits_infer.py)
subprocess.run(["python", "vits_infer.py", "--ssml", "output.ssml", "--out", "tts.wav"])
```
---
## 7.4 OBS 與多媒體輸出
### 7.4.1 OBS 基礎架構
1. **來源 (Source)**:
- **音訊來源**:TTS、歌聲檔 (`tts.wav` / `song.wav`)。
- **視訊來源**:Live2D、3D avatar、預先渲染的動畫。
2. **場景 (Scene)**:將音訊與視訊組合成 **直播畫面**,可預設「開場」「表演」「互動」等多個場景。
3. **插件**:
- **OBS WebSocket**:允許外部腳本遠端控制場景切換與音量。
- **StreamElements / Streamlabs**:即時彈幕、禮物特效。
### 7.4.2 用 Python 控制 OBS(示例)
```python
import websockets, json, asyncio
OBS_HOST = "ws://localhost:4455"
PASSWORD = "your_obs_password"
async def obs_request(msg: dict):
async with websockets.connect(OBS_HOST) as ws:
# 認證
await ws.send(json.dumps({"op": 1, "d": {"rpcVersion": 1, "authentication": PASSWORD}}))
await ws.recv() # 讀取回應
# 發送指令
await ws.send(json.dumps({"op": 6, "d": msg}))
return await ws.recv()
# 切換到表演場景
payload = {
"requestType": "SetCurrentProgramScene",
"requestData": {"sceneName": "Performance"}
}
asyncio.run(obs_request(payload))
```
> **注意**:OBS WebSocket 需要在 OBS 「工具 → WebSocket Server」中啟用,並設置密碼。
---
## 7.5 即時互動:Discord / Telegram 機器人
### 7.5.1 為什麼選擇 Discord / Telegram?
- **即時性**:WebSocket 連線維持低延遲。
- **豐富的 API**:訊息、表情、按鈕、語音頻道皆可程式化。
- **社群成熟**:許多粉絲已在這兩平台活躍。
### 7.5.2 Bot 基礎架構圖
```mermaid
sequenceDiagram
participant User as 粉絲
participant Bot as Bot (Discord/Telegram)
participant LLM as LLM 生成回覆
participant TTS as TTS 引擎
participant OBS as OBS (WebSocket)
User->>Bot: 發送文字訊息
Bot->>LLM: 文字→Prompt
LLM-->>Bot: JSON 回覆
Bot->>TTS: 文字→SSML
TTS-->>Bot: 音檔
Bot->>OBS: 播放音檔 + 切換互動場景
Bot-->>User: 文字或語音回覆
```
### 7.5.3 Discord Bot 範例(Python + discord.py)
```python
import discord, json, openai, asyncio, websockets
from pathlib import Path
intents = discord.Intents.default()
intents.message_content = True
bot = discord.Client(intents=intents)
# 1. LLM 產生回覆
async def generate_reply(message: str) -> dict:
prompt = f"你是虛擬偶像星瀾,請以甜美且帶點電子音的語氣回覆以下訊息:{message}"
resp = await openai.ChatCompletion.acreate(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.8,
response_format={"type": "json_object"}
)
return json.loads(resp.choices[0].message.content)
# 2. 呼叫本地 TTS(VITS LoRA)
async def synthesize(text: str, filename: str = "reply.wav"):
ssml = f"<speak>{text}</speak>"
Path("tmp.ssml").write_text(ssml, encoding="utf-8")
proc = await asyncio.create_subprocess_exec(
"python", "vits_infer.py", "--ssml", "tmp.ssml", "--out", filename,
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
await proc.communicate()
return filename
# 3. 觸發 OBS 切換場景並播放音檔
async def play_in_obs(audio_path: str):
async with websockets.connect("ws://localhost:4455") as ws:
await ws.send(json.dumps({"op":1,"d":{"rpcVersion":1,"authentication":"your_obs_password"}}))
await ws.recv()
# 切換至互動場景
await ws.send(json.dumps({"op":6,"d":{"requestType":"SetCurrentProgramScene","requestData":{"sceneName":"Interaction"}}}))
await ws.recv()
# 更新音訊來源(假設已有 Audio Source 名稱為 'Voice')
await ws.send(json.dumps({"op":6,"d":{"requestType":"SetSourceSettings","requestData":{"sourceName":"Voice","sourceSettings":{"local_file":audio_path}}}}))
await ws.recv()
@bot.event
async def on_message(message: discord.Message):
if message.author.bot:
return
# 只回覆指令前綴 "!" 以免濫用
if not message.content.startswith("!"):
return
user_text = message.content[1:].strip()
reply_json = await generate_reply(user_text)
reply_text = reply_json.get("reply", "…")
audio_file = await synthesize(reply_text)
await play_in_obs(audio_file)
# 同時回傳文字版給粉絲
await message.channel.send(reply_text)
bot.run("YOUR_DISCORD_BOT_TOKEN")
```
> **重點說明**:
> - 使用 **OpenAI function calling** 可保證回覆結構化,減少後處理錯誤。
> - Audio source 需在 OBS 預先設定為 **Media Source**,允許外部腳本指定本地檔案路徑。
> - 為防止濫用,建議在 **Discord 伺服器** 加入 **Rate‑limit** 或 **權限檢查**。
### 7.5.4 Telegram Bot(python‑telegram‑bot)簡易實作
```python
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, filters, ContextTypes
import openai, json, asyncio, subprocess, websockets
async def reply(update: Update, context: ContextTypes.DEFAULT_TYPE):
user_msg = update.message.text
# LLM 產生回覆
resp = await openai.ChatCompletion.acreate(
model="gpt-4o-mini",
messages=[{"role": "user", "content": f"你是星瀾,請以甜美語氣回覆:{user_msg}"}],
response_format={"type": "json_object"})
reply_json = json.loads(resp.choices[0].message.content)
reply_text = reply_json.get("reply", "…")
# TTS 合成(使用本地腳本)
ssml = f"<speak>{reply_text}</speak>"
Path("tmp.ssml").write_text(ssml, encoding="utf-8")
subprocess.run(["python", "vits_infer.py", "--ssml", "tmp.ssml", "--out", "reply.wav"])
# OBS 播放
async with websockets.connect("ws://localhost:4455") as ws:
await ws.send(json.dumps({"op":1,"d":{"rpcVersion":1,"authentication":"your_obs_password"}}))
await ws.recv()
await ws.send(json.dumps({"op":6,"d":{"requestType":"SetCurrentProgramScene","requestData":{"sceneName":"Interaction"}}}))
await ws.recv()
await ws.send(json.dumps({"op":6,"d":{"requestType":"SetSourceSettings","requestData":{"sourceName":"Voice","sourceSettings":{"local_file":"reply.wav"}}}}))
await ws.recv()
# 回傳文字給使用者
await update.message.reply_text(reply_text)
app = ApplicationBuilder().token("YOUR_TELEGRAM_BOT_TOKEN").build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, reply))
app.run_polling()
```
---
## 7.6 完整自動化管線:從腳本生成到直播上線
### 7.6.1 條件與前置設定
| 項目 | 推薦方案 | 版本/設定說明 |
|------|----------|----------------|
| 作業系統 | Ubuntu 22.04 LTS | 支援 GPU 驅動 (CUDA 12) |
| GPU | NVIDIA RTX 4090 | 至少 24GB 記憶體,適用 VITS LoRA、DiffSinger |
| LLM 服務 | OpenAI GPT‑4o / 本地 Mistral‑7B‑Instruct + llama‑cpp | 依需求選擇雲端或本地 |
| TTS 引擎 | VITS‑LoRA (自訂聲線) + Azure TTS 作備援 | 兩者互補 |
| 直播平台 | YouTube Live / Twitch |
| 互動平台 | Discord (官方伺服器) + Telegram 群組 |
| OBS | 29.x + OBS‑WebSocket 5.1 |
| 任務排程 | **Cron** + **systemd** 服務 | 確保腳本在系統啟動時自動運行 |
### 7.6.2 Pipeline 程式碼概覽(master.py)
```python
# master.py – 完整自動化工作流入口
import asyncio, json, datetime, os
from pathlib import Path
from utils import (
llm_generate, # LLM 產生腳本
ssml_wrap, # 產生 SSML
tts_synthesize, # VITS LoRA 合成
obs_control, # OBS WebSocket 控制
discord_bot, # 啟動 Discord Bot
telegram_bot # 啟動 Telegram Bot
)
async def daily_script_job():
"""每日凌晨 02:00 自動產出當日直播腳本並推送至 OBS 場景"""
now = datetime.datetime.now().strftime("%Y-%m-%d")
prompt = f"為 {now} 的《星光音樂會》產生 5 分鐘的開場腳本,請回傳 JSON,包含 'script' 與 'keywords'。"
data = await llm_generate(prompt)
script, kw = data["script"], data["keywords"]
# 保存腳本供機器人使用
Path("today_script.json").write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
# 生成 SSML 並 TTS
ssml = ssml_wrap(script, kw)
await tts_synthesize(ssml, out_path="opening.wav")
# OBS 切換至 Opening 場景並播放
await obs_control.set_scene("Opening")
await obs_control.play_audio("opening.wav")
print("[INFO] 今日開場腳本已上線")
async def main():
# 啟動即時互動機器人(背景任務)
asyncio.create_task(discord_bot.run())
asyncio.create_task(telegram_bot.run())
# 每日排程
while True:
now = datetime.datetime.now()
if now.hour == 2 and now.minute == 0:
await daily_script_job()
await asyncio.sleep(60) # 每分鐘檢查一次
if __name__ == "__main__":
asyncio.run(main())
```
> `utils` 內部實作即為第 7.3、7.4、7.5 小節的函式,將各模組解耦,便於未來替換模型或平台。
### 7.6.3 部署與監控
1. **建立 systemd 服務** (`/etc/systemd/system/virtual_idol.service`)
```ini
[Unit]
Description=Virtual Idol Automation Service
After=network.target
[Service]
Type=simple
User=idol_user
WorkingDirectory=/home/idol_user/virtual_idol
ExecStart=/usr/bin/python3 /home/idol_user/virtual_idol/master.py
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
```
- `systemctl enable --now virtual_idol` 即可自動啟動。
2. **日誌**:使用 `journalctl -u virtual_idol -f` 觀察即時輸出。
3. **健康檢查**:可在 `cron` 內加入 `curl -s http://localhost:8000/health`(在 `master.py` 加一個簡易 FastAPI 健康端點),讓監控系統(如 Prometheus + Grafana)即時通知服務異常。
---
## 7.7 常見問題與最佳實踐
| 問題 | 可能原因 | 解決方案 |
|------|----------|----------|
| **Bot 回覆延遲 > 5 秒** | LLM 請求超時、GPU 資源不夠 | 調整 `temperature`、使用 `max_tokens` 限制;升級 GPU 或使用雲端推理服務。 |
| **OBS 音訊不同步** | Media Source 緩衝策略不當 | 在 OBS 設定 `Media Source` → `Restart playback when source becomes active` 並關閉 `Show nothing when playback ends`。 |
| **Discord Bot 被限速** | 訊息過於頻繁、未加 Rate‑limit | 使用 `discord.ext.commands.CooldownMapping` 或自行在 `on_message` 加入時間戳檢查。 |
| **TTS 音質失真** | LoRA 微調資料不足或過度擬合 | 擴充語音資料集至至少 **30 分鐘**,使用 **AdamW** 小學習率微調,並在訓練後使用 **EMA** 平滑模型。 |
| **語意偏離角色設定** | Prompt 未明確限定角色語調 | 在每次 LLM 呼叫前加入 **System Prompt**:`You are star‑idol "星瀾" ...`,並使用 **function calling** 強制輸出 JSON。 |
### 7.7.1 安全與隱私
- **Token 管理**:所有 API 金鑰、Discord/Telegram Bot Token、OBS 密碼皆放置於環境變數或 **Vault**,不要硬編碼於程式。
- **頻率限制**:對外部 LLM / TTS 服務設定每日/每秒上限,防止意外帳單暴增。
- **資料合規**:若收集粉絲文字訊息做模型微調,必須取得明確同意並在隱私政策中說明用途。
---
## 7.8 小結
本章提供了 **從概念腳本到全自動直播** 的完整技術藍圖,核心流程可概括為:
1. **LLM 產生結構化腳本**(Prompt Engineering + Function Calling)。
2. **情感化 SSML + LoRA‑VITS/TTS** 產出自然語音,或 DiffSinger 產出歌曲。
3. **OBS WebSocket** 讓音視訊自動切換、播放、特效同步。
4. **Discord / Telegram Bot** 捕捉粉絲即時訊息,回饋文字與語音,形成閉環互動。
5. **系統化部署**(systemd、健康檢查、日誌)確保 24/7 穩定運行。
透過本章的實作範例與最佳實踐,讀者即可在自己的虛擬偶像專案中快速建立 **自動化內容創作管線**,即使在高流量直播期間,也能保持即時、個性化且高品質的粉絲互動,為後續的 **品牌運營與商業變現** 打下堅實基礎。