File size: 4,619 Bytes
14a6e16
 
 
 
 
c02528e
 
14a6e16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1d3143e
14a6e16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c02528e
 
 
14a6e16
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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

    @abc.abstractmethod
    def _get_config_page(self):
        """要求返回2个参数:config和inputs
        config: gr.Group对象,用于包裹所有的输入项
        inputs: 一个列表,包含所有的输入项,用于后续的事件绑定,列表的顺序必须和后续_generate方法中参数args的顺序一致

        例如:
        :return: config, inputs
        """

    @abc.abstractmethod
    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
        """

    @abc.abstractmethod
    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="合成", 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