import os
import numpy as np
import cv2
import subprocess
import time
import threading
import queue
from scipy.io import wavfile
from talkingface.audio_model import AudioModel
from talkingface.render_model import RenderModel

# 初始化模型
audioModel = AudioModel()
audioModel.loadModel("checkpoint/audio.pkl")

renderModel = RenderModel()
renderModel.loadModel("checkpoint/render.pth")

# 定义参数
sample_rate = 16000
frame_rate = 25
frame_duration = 1 / frame_rate
running = True

# 创建命名管道
video_pipe_path = 'video_pipe'
audio_pipe_path = 'audio_pipe'

if not os.path.exists(video_pipe_path):
    os.mkfifo(video_pipe_path)
if not os.path.exists(audio_pipe_path):
    os.mkfifo(audio_pipe_path)

# FFmpeg 命令
ffmpeg_command = [
    'ffmpeg',
    '-y',
    '-probesize', '32',
    '-analyzeduration', '0',
    '-f', 'rawvideo',
    '-pix_fmt', 'bgr24',
    '-s', '640x480',
    '-r', str(frame_rate),
    '-i', video_pipe_path,
    '-f', 's16le',
    '-ar', str(sample_rate),
    '-ac', '1',
    '-i', audio_pipe_path,
    '-c:v', 'libx264',
    '-pix_fmt', 'yuv420p',
    '-c:a', 'aac',
    '-b:a', '128k',
    '-f', 'flv',
    'rtmp://localhost/live/livestream'
]

# 启动 FFmpeg
ffmpeg_process = subprocess.Popen(ffmpeg_command)

# 数据队列
data_queue = queue.Queue(maxsize=50)  # 限制队列大小，防止内存占用过多

def audio_thread():
    audio_chunk_size = int(sample_rate * frame_duration)
    silence_chunk = np.zeros(audio_chunk_size, dtype=np.int16)
    audio_data_buffer = np.array([], dtype=np.int16)

    with open(audio_pipe_path, 'wb') as audio_pipe:
        while running:
            # 读取音频文件或使用静音数据
            # ...（省略音频文件读取代码）

            # 音频数据处理
            while len(audio_data_buffer) >= audio_chunk_size:
                current_chunk = audio_data_buffer[:audio_chunk_size]
                audio_data_buffer = audio_data_buffer[audio_chunk_size:]

                # 将音频数据写入音频管道
                audio_pipe.write(current_chunk.tobytes())
                audio_pipe.flush()

                # 生成 mouth_frame
                pcm_data = current_chunk.astype(np.float32) / 32768.0
                mouth_frame = audioModel.interface_frame(pcm_data)

                # 将数据放入队列
                data_queue.put(mouth_frame)

                time.sleep(frame_duration)

def video_thread():
    with open(video_pipe_path, 'wb') as video_pipe:
        while running:
            try:
                # 从队列中获取 mouth_frame
                mouth_frame = data_queue.get(timeout=1)
            except queue.Empty:
                continue

            # 生成视频帧
            frame = renderModel.interface(mouth_frame)

            # 确保帧大小匹配
            frame = cv2.resize(frame, (640, 480))

            # 将视频帧写入视频管道
            video_pipe.write(frame.tobytes())
            video_pipe.flush()

            time.sleep(frame_duration)

# 启动线程
audio_thread = threading.Thread(target=audio_thread)
video_thread = threading.Thread(target=video_thread)

audio_thread.start()
video_thread.start()

# 主线程等待
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    running = False
    audio_thread.join()
    video_thread.join()
    ffmpeg_process.terminate()
    if os.path.exists(video_pipe_path):
        os.remove(video_pipe_path)
    if os.path.exists(audio_pipe_path):
        os.remove(audio_pipe_path)   pls modify it