Spaces:
Runtime error
Runtime error
import abc | |
import io | |
import scipy.io.wavfile as wavfile | |
from pydub import AudioSegment | |
import traceback | |
import gradio as gr | |
def mix_background_music(original_audio, 背景音乐, TTS_up, bg_up): | |
original_audio = original_audio + TTS_up | |
ori_out = io.BytesIO() | |
original_audio.export(ori_out, format="mp3") | |
ori_out.seek(0) | |
original_audio_bytes = ori_out.read() | |
if 背景音乐 is None: # 没有背景音乐 | |
return original_audio_bytes, None | |
else: # 有背景音乐 | |
# 读取用户上传的背景音乐文件 | |
wav_io = io.BytesIO() | |
wavfile.write(wav_io, 背景音乐[0], 背景音乐[1]) | |
wav_io.seek(0) | |
background_music = AudioSegment.from_wav(wav_io) | |
background_music = background_music + bg_up | |
# 将背景音乐合并到原始音频中 | |
combined = original_audio.overlay(background_music) | |
# 使用BytesIO导出合并后的音频为字节串 | |
mix_out = io.BytesIO() | |
combined.export(mix_out, format="mp3") | |
mix_out.seek(0) # 重置指针到开始位置 | |
combined_audio_bytes = mix_out.read() | |
return original_audio_bytes, combined_audio_bytes | |
class Base_TTS(metaclass=abc.ABCMeta): | |
default_show = False | |
def _get_config_page(self): | |
"""要求返回2个参数:config和inputs | |
config: gr.Group对象,用于包裹所有的输入项 | |
inputs: 一个列表,包含所有的输入项,用于后续的事件绑定,列表的顺序必须和后续_generate方法中参数args的顺序一致 | |
例如: | |
:return: config, inputs | |
""" | |
def _generate(self, text, *args): | |
"""要求返回一个AudioSegment对象 | |
:param text: str,要转换为语音的文本 | |
:param args: 其他参数,与_get_config_page方法中的inputs一一对应 | |
:return: original_audio | |
示例: | |
original_audio = AudioSegment.from_file(io.BytesIO(original_audio_bytes), format="mp3") | |
return original_audio | |
""" | |
def get_name(self): | |
"""要求返回一个str,是TTS的名称 | |
:return: name | |
示例: | |
return '原神语音合成引擎' | |
""" | |
def is_show(self): | |
""" | |
是否显示这个TTS | |
:return: True or False | |
""" | |
return True | |
def _get_submit_button(self): | |
""" | |
要求返回1个参数:btn | |
btn: gr.Button对象,是提交按钮 | |
:return: btn | |
""" | |
btn = gr.Button(value="test提交", variant="primary", interactive=True, visible=False) | |
return btn | |
def get_config_page(self): | |
self.config, self.inputs = self._get_config_page() | |
if self.default_show: | |
self.config.visible = True | |
else: | |
self.config.visible = False | |
def get_submit_button(self): | |
self.btn = self._get_submit_button() | |
if self.default_show: | |
self.btn.visible = True | |
else: | |
self.btn.visible = False | |
def set_visible(self, visible: bool): | |
# 检查是否已经获取了config和btn | |
if not hasattr(self, 'config') or not hasattr(self, 'btn'): | |
raise Exception('请先调用get_config_page和get_submit_button方法') | |
self.btn.visible = visible | |
self.config.visible = visible | |
def create_interface_event(self, text, audio, TTS_up, bg_up, text_output, ori_audio_output, mix_audio_output): | |
"""如果交互方法只是的点击提交按钮,可以不用重写这个方法""" | |
# 检查是否已经获取了config和btn | |
if not hasattr(self, 'config') or not hasattr(self, 'btn'): | |
raise Exception('请先调用get_config_page和get_submit_button方法') | |
self.btn.click(self.generate, inputs=[ | |
text, | |
audio, | |
TTS_up, | |
bg_up | |
] + self.inputs, | |
outputs=[text_output, ori_audio_output, mix_audio_output]) | |
def generate(self, text, 背景音乐, TTS_up, bg_up, *args): | |
try: | |
original_audio = self._generate(text, *args) | |
return None, *mix_background_music(original_audio, 背景音乐, TTS_up, bg_up) | |
except Exception as e: | |
msg = traceback.format_exc() | |
return msg + '\n\n' + str(e), None, None | |