[2noise/ChatTTS]请问使用webui进行流式推理的时候音频播放为什么会有5秒钟左右的延迟?

2024-08-19 749 views
5

按理说500ms一个chunk,推理+播放延迟应该不会超过1-2秒吧,推理完成第1个chunk应该就会开始播放音频了,是gradio的问题吗?我的设备没有播放器,只能用webui播放音频,如果直接用pyaudio本地播放会不会没有这么高延迟?

回答

6

增大输出速度会引入爆音,可以调节InferCodeParamsstream_speed参数以查看效果。

4

流式首包1-2秒,设备没有播放器可以拿普通电脑作客户端播放声音,给远程有gpu的服务端请求流式获取声音数据

7

嗯嗯,我现在就是这样实现了,速度确实快了一些,但是刚播放时会有一段噪音,期间也会有电流音,请问这是什么情况呢

0

应该是写入不够快声音断断续续导致,开始播放时比较容易出现。最好是推理足够快(比播放快),而且客户端那边也要非阻塞的持续将声音数据写入播放器 可以在客户端实现一个持续获取网络数据的generator,播放器同时进行写入和播放。示例

import io
import threading

class Player:
    def __init__(self,waittime_topause=600):
        self.bio = io.BytesIO()
        self.lock = threading.Lock()
        self.seek_index = 0
        self.waittime_topause=waittime_topause
        self.finish=False
    def _write(self,write_binary):
        with self.lock:
            self.bio.write(write_binary)
    def _read(self,):
        with self.lock:
            self.bio.seek(self.seek_index)
            read_binary = self.bio.read()
            self.seek_index += len(read_binary)
        return read_binary
    def write(self,voice_generator):
        self.finish = False
        for audio_binary in voice_generator:
            self._write(audio_binary)
        self.finish=True
    def play(self,waittime_tostart,auto_end=False):
        self.end=False## force ending
        import pyaudio
        # 初始化PyAudio对象
        p = pyaudio.PyAudio()

        # 设置音频流参数
        FORMAT = pyaudio.paInt16  # 16位深度
        CHANNELS = 1  # 单声道
        RATE = 24000  # 采样率
        CHUNK = 1024  # 每块音频数据大小

        # 打开输出流(扬声器)
        stream_out = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True)

        print("开始流式音频播放...")
        import time

        time.sleep(waittime_tostart)

        wait_time = 0
        while (self.bio.tell() > self.seek_index) | (
            wait_time < self.waittime_topause
        ):

            if self.bio.tell() > self.seek_index:
                read_data = self._read()
                stream_out.write(read_data)
                wait_time = 0
            # 如果不设置自动结束,就等待一段时间,如果一直没有新写入,就自动结束。如果设置了自动结束,就在写操作结束时结束播放
            else:

                if self.end:
                    print("用户手动终止")
                    break
                elif auto_end & self.finish:
                    print("写操作完成,自动结束。")
                    break
                else:
                    time.sleep(0.5)
                    wait_time += 0.5

        print("完成流式音频播放...")
        stream_out.stop_stream()
        stream_out.close()

    # 开始音频写入。可支持多次音频写入.streamchat是一个音频编码字节流iterator
    def start_writing(self, streamchat):
        self.writer = threading.Thread(target=self.write, args=(streamchat,))
        self.writer.start()

    # 开始音频播放
    def start_playing(self, waittime_tostart=5):
        self.player = threading.Thread(target=self.play, args=(waittime_tostart,))
        self.player.start()

    # 一次完整的音频写入+播放
    def run(self, streamchat, waittime_tostart=5):
        self.writer = threading.Thread(target=self.write, args=(streamchat,))
        self.player = threading.Thread(target=self.play, args=(waittime_tostart, True))
        self.writer.start()
        self.player.start()
        self.writer.join()
        self.player.join()

def generate(text):
    #网络请求流式获取音频字节流数据
    yield audio_binary
player=Player()
streamchat=generate(text)
player.run(streamchat)