All checks were successful
Build and Deploy Backend / build-and-deploy (push) Successful in 6m7s
71 lines
1.8 KiB
Python
71 lines
1.8 KiB
Python
"""
|
||
引导语 Opus 生成服务
|
||
|
||
为故事/音乐生成一句引导语(如"正在为您播放,卡皮巴拉蹦蹦蹦"),
|
||
转为 Opus 帧 JSON 字符串,直接存入数据库字段。
|
||
"""
|
||
import asyncio
|
||
import logging
|
||
import random
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
TTS_VOICE = 'zh-CN-XiaoxiaoNeural'
|
||
|
||
STORY_PROMPTS = [
|
||
"正在为您播放,{}",
|
||
"请欣赏故事,{}",
|
||
"即将为您播放,{}",
|
||
"为您带来,{}",
|
||
"让我们聆听,{}",
|
||
"接下来请欣赏,{}",
|
||
"为您献上,{}",
|
||
]
|
||
|
||
MUSIC_PROMPTS = [
|
||
"正在为您播放,{}",
|
||
"请享受音乐,{}",
|
||
"即将为您播放,{}",
|
||
"为您带来,{}",
|
||
"让我们聆听,{}",
|
||
"接下来请欣赏,{}",
|
||
"为您献上,{}",
|
||
]
|
||
|
||
|
||
def generate_intro_opus(title: str, content_type: str = 'story') -> str:
|
||
"""
|
||
为指定标题生成引导语 Opus JSON。
|
||
|
||
Args:
|
||
title: 故事或音乐标题
|
||
content_type: 'story' 或 'music'
|
||
|
||
Returns:
|
||
Opus 帧 JSON 字符串(与 opus_url 指向的格式一致)
|
||
"""
|
||
prompts = STORY_PROMPTS if content_type == 'story' else MUSIC_PROMPTS
|
||
text = random.choice(prompts).format(title)
|
||
logger.info(f'生成引导语: "{text}"')
|
||
|
||
# edge-tts 合成 MP3
|
||
mp3_bytes = asyncio.run(_synthesize(text))
|
||
|
||
# MP3 → Opus 帧 JSON
|
||
from apps.stories.services.opus_converter import convert_mp3_to_opus_json
|
||
opus_json = convert_mp3_to_opus_json(mp3_bytes)
|
||
|
||
return opus_json
|
||
|
||
|
||
async def _synthesize(text: str) -> bytes:
|
||
"""使用 edge-tts 合成语音,返回 MP3 bytes"""
|
||
import edge_tts
|
||
|
||
communicate = edge_tts.Communicate(text, TTS_VOICE)
|
||
audio_chunks = []
|
||
async for chunk in communicate.stream():
|
||
if chunk['type'] == 'audio':
|
||
audio_chunks.append(chunk['data'])
|
||
return b''.join(audio_chunks)
|