|
import asyncio |
|
import unittest |
|
import os |
|
import sys |
|
from pathlib import Path |
|
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent)) |
|
|
|
from app.utils import utils |
|
from app.services import voice as vs |
|
|
|
temp_dir = utils.storage_dir("temp") |
|
|
|
text_en = """ |
|
What is the meaning of life? |
|
This question has puzzled philosophers, scientists, and thinkers of all kinds for centuries. |
|
Throughout history, various cultures and individuals have come up with their interpretations and beliefs around the purpose of life. |
|
Some say it's to seek happiness and self-fulfillment, while others believe it's about contributing to the welfare of others and making a positive impact in the world. |
|
Despite the myriad of perspectives, one thing remains clear: the meaning of life is a deeply personal concept that varies from one person to another. |
|
It's an existential inquiry that encourages us to reflect on our values, desires, and the essence of our existence. |
|
""" |
|
|
|
text_zh = """ |
|
预计未来3天深圳冷空气活动频繁,未来两天持续阴天有小雨,出门带好雨具; |
|
10-11日持续阴天有小雨,日温差小,气温在13-17℃之间,体感阴凉; |
|
12日天气短暂好转,早晚清凉; |
|
""" |
|
|
|
voice_rate=1.0 |
|
voice_volume=1.0 |
|
|
|
class TestVoiceService(unittest.TestCase): |
|
def setUp(self): |
|
self.loop = asyncio.new_event_loop() |
|
asyncio.set_event_loop(self.loop) |
|
|
|
def tearDown(self): |
|
self.loop.close() |
|
|
|
def test_siliconflow(self): |
|
voice_name = "siliconflow:FunAudioLLM/CosyVoice2-0.5B:alex-Male" |
|
voice_name = vs.parse_voice_name(voice_name) |
|
|
|
async def _do(): |
|
parts = voice_name.split(":") |
|
if len(parts) >= 3: |
|
model = parts[1] |
|
|
|
voice_with_gender = parts[2] |
|
voice = voice_with_gender.split("-")[0] |
|
|
|
full_voice = f"{model}:{voice}" |
|
voice_file = f"{temp_dir}/tts-siliconflow-{voice}.mp3" |
|
subtitle_file = f"{temp_dir}/tts-siliconflow-{voice}.srt" |
|
sub_maker = vs.siliconflow_tts( |
|
text=text_zh, model=model, voice=full_voice, voice_file=voice_file, voice_rate=voice_rate, voice_volume=voice_volume |
|
) |
|
if not sub_maker: |
|
self.fail("siliconflow tts failed") |
|
vs.create_subtitle(sub_maker=sub_maker, text=text_zh, subtitle_file=subtitle_file) |
|
audio_duration = vs.get_audio_duration(sub_maker) |
|
print(f"voice: {voice_name}, audio duration: {audio_duration}s") |
|
else: |
|
self.fail("siliconflow invalid voice name") |
|
|
|
self.loop.run_until_complete(_do()) |
|
|
|
def test_azure_tts_v1(self): |
|
voice_name = "zh-CN-XiaoyiNeural-Female" |
|
voice_name = vs.parse_voice_name(voice_name) |
|
print(voice_name) |
|
|
|
voice_file = f"{temp_dir}/tts-azure-v1-{voice_name}.mp3" |
|
subtitle_file = f"{temp_dir}/tts-azure-v1-{voice_name}.srt" |
|
sub_maker = vs.azure_tts_v1( |
|
text=text_zh, voice_name=voice_name, voice_file=voice_file, voice_rate=voice_rate |
|
) |
|
if not sub_maker: |
|
self.fail("azure tts v1 failed") |
|
vs.create_subtitle(sub_maker=sub_maker, text=text_zh, subtitle_file=subtitle_file) |
|
audio_duration = vs.get_audio_duration(sub_maker) |
|
print(f"voice: {voice_name}, audio duration: {audio_duration}s") |
|
|
|
def test_azure_tts_v2(self): |
|
voice_name = "zh-CN-XiaoxiaoMultilingualNeural-V2-Female" |
|
voice_name = vs.parse_voice_name(voice_name) |
|
print(voice_name) |
|
|
|
async def _do(): |
|
voice_file = f"{temp_dir}/tts-azure-v2-{voice_name}.mp3" |
|
subtitle_file = f"{temp_dir}/tts-azure-v2-{voice_name}.srt" |
|
sub_maker = vs.azure_tts_v2( |
|
text=text_zh, voice_name=voice_name, voice_file=voice_file |
|
) |
|
if not sub_maker: |
|
self.fail("azure tts v2 failed") |
|
vs.create_subtitle(sub_maker=sub_maker, text=text_zh, subtitle_file=subtitle_file) |
|
audio_duration = vs.get_audio_duration(sub_maker) |
|
print(f"voice: {voice_name}, audio duration: {audio_duration}s") |
|
|
|
self.loop.run_until_complete(_do()) |
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
unittest.main() |