main_sync.py 11.2 KB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AIfeng/2025-07-02 14:14:18
同步版本主程序入口
基于eman-Fay-main-copy的实现模式
"""

import os
import sys
import time
import threading
import signal
from flask import Flask

# 在导入utils模块之前先创建必要目录
def _ensure_basic_dirs():
    """确保基础目录存在"""
    basic_dirs = ['logs', 'cache', 'temp', 'audio']
    for directory in basic_dirs:
        if not os.path.exists(directory):
            try:
                os.makedirs(directory, exist_ok=True)
            except Exception as e:
                print(f"创建目录失败 {directory}: {e}")

# 初始化基础目录
_ensure_basic_dirs()

# 现在可以安全导入utils模块
from utils import util
from utils.config_util import get_server_config, get_config
from recorder_sync import RecorderSync
from funasr_asr_sync import FunASRSync

# 全局变量
recorder = None
funasr_client = None
flask_app = None
flask_thread = None
running = False

def signal_handler(signum, frame):
    """
    信号处理器
    """
    print("\n接收到退出信号,正在关闭...")
    stop_all_services()
    sys.exit(0)

def cleanup_temp_files():
    """
    清理临时文件
    """
    try:
        # 清理音频文件
        audio_dir = "audio"
        if os.path.exists(audio_dir):
            for file in os.listdir(audio_dir):
                if file.endswith(('.wav', '.mp3', '.pcm')):
                    file_path = os.path.join(audio_dir, file)
                    try:
                        os.remove(file_path)
                        print(f"已删除音频文件: {file_path}")
                    except Exception as e:
                        print(f"删除音频文件失败 {file_path}: {e}")
        
        # 清理日志文件(可选)
        log_dir = "logs"
        if os.path.exists(log_dir):
            for file in os.listdir(log_dir):
                if file.endswith('.log') and file.startswith('temp_'):
                    file_path = os.path.join(log_dir, file)
                    try:
                        os.remove(file_path)
                        print(f"已删除临时日志文件: {file_path}")
                    except Exception as e:
                        print(f"删除临时日志文件失败 {file_path}: {e}")
                        
    except Exception as e:
        print(f"清理临时文件时出错: {e}")

def create_directories():
    """
    创建必要的目录
    """
    directories = ['audio', 'logs', 'cache', 'temp']
    
    for directory in directories:
        if not os.path.exists(directory):
            try:
                os.makedirs(directory)
                print(f"已创建目录: {directory}")
            except Exception as e:
                print(f"创建目录失败 {directory}: {e}")

def init_funasr_service():
    """
    初始化FunASR服务
    """
    global funasr_client
    
    try:
        print("正在启动FunASR服务...")
        # 获取当前用户名,如果没有则使用默认值
        username = fay_core.fay_core_instance.get_current_user() or "default_user"
        funasr_client = FunASRSync(username=username)
        funasr_client.start()
        print("FunASR服务启动成功")
        return True
    except Exception as e:
        print(f"启动FunASR服务失败: {e}")
        return False

def init_recorder_service():
    """
    初始化录音服务
    """
    global recorder
    
    try:
        print("正在启动录音服务...")
        # 使用fay_core实例作为参数
        recorder = RecorderSync(fay=fay_core.fay_core_instance)
        
        print("录音服务初始化成功")
        return True
    except Exception as e:
        print(f"启动录音服务失败: {e}")
        return False

def init_flask_service():
    """
    初始化Flask服务
    """
    global flask_app, flask_thread
    
    try:
        print("正在启动Flask服务...")
        
        # 导入Flask应用
        from server_recording_api_sync import app as sync_app
        flask_app = sync_app
        
        # 获取服务器配置
        server_config = get_server_config()
        host = server_config.get('host', '0.0.0.0')
        port = server_config.get('port', 5050)
        debug = server_config.get('debug', False)
        
        # 在单独线程中启动Flask
        def run_flask():
            flask_app.run(host=host, port=port, debug=debug, use_reloader=False)
        
        flask_thread = threading.Thread(target=run_flask, daemon=True)
        flask_thread.start()
        
        # 等待服务启动
        time.sleep(2)
        
        print(f"Flask服务启动成功: http://{host}:{port}")
        return True
        
    except Exception as e:
        print(f"启动Flask服务失败: {e}")
        return False

def start_all_services():
    """
    启动所有服务
    """
    global running
    
    print("=" * 50)
    print("启动eman_one同步版本服务")
    print("=" * 50)
    
    # 清理临时文件
    cleanup_temp_files()
    
    # 创建必要目录
    create_directories()
    
    # 启动服务
    services_started = 0
    total_services = 3
    
    # 1. 启动FunASR服务
    if init_funasr_service():
        services_started += 1
    
    # 2. 启动录音服务
    if init_recorder_service():
        services_started += 1
    
    # 3. 启动Flask服务
    if init_flask_service():
        services_started += 1
    
    if services_started == total_services:
        running = True
        print(f"\n所有服务启动成功 ({services_started}/{total_services})")
        print("系统已就绪!")
        
        # 显示访问地址
        server_config = get_server_config()
        port = server_config.get('port', 5050)
        print(f"\n访问地址:")
        print(f"  - 语音测试页面: http://localhost:{port}/voice_test_sync.html")
        print(f"  - API接口: http://localhost:{port}/api/")
        
        return True
    else:
        print(f"\n服务启动失败 ({services_started}/{total_services})")
        stop_all_services()
        return False

def stop_all_services():
    """
    停止所有服务
    """
    global running, recorder, funasr_client
    
    print("\n正在停止所有服务...")
    running = False
    
    # 停止录音服务
    if recorder:
        try:
            recorder.stop_recording()
            print("录音服务已停止")
        except Exception as e:
            print(f"停止录音服务时出错: {e}")
        recorder = None
    
    # 停止FunASR服务
    if funasr_client:
        try:
            funasr_client.end()
            print("FunASR服务已停止")
        except Exception as e:
            print(f"停止FunASR服务时出错: {e}")
        funasr_client = None
    
    print("所有服务已停止")

def restart_all_services():
    """
    重启所有服务
    """
    print("\n正在重启所有服务...")
    stop_all_services()
    time.sleep(2)
    return start_all_services()

def show_status():
    """
    显示系统状态
    """
    print("\n=== 系统状态 ===")
    print(f"运行状态: {'运行中' if running else '已停止'}")
    print(f"FunASR服务: {'运行中' if funasr_client and funasr_client.is_connected() else '未连接'}")
    print(f"录音服务: {'就绪' if recorder else '未初始化'}")
    print(f"Flask服务: {'运行中' if flask_thread and flask_thread.is_alive() else '未运行'}")
    
    if recorder:
        print(f"录音状态: {'录音中' if recorder.is_recording() else '待机'}")
    
    # 显示配置信息
    server_config = get_server_config()
    print(f"服务端口: {server_config.get('port', 5050)}")
    print(f"ASR模式: {get_config('asr.mode', 'funasr')}")
    print("=" * 20)

def console_input_listener():
    """
    控制台输入监听器
    """
    print("\n控制台命令:")
    print("  start  - 启动服务")
    print("  stop   - 停止服务")
    print("  restart- 重启服务")
    print("  status - 显示状态")
    print("  exit   - 退出程序")
    print("  help   - 显示帮助")
    
    while True:
        try:
            command = input("\n请输入命令: ").strip().lower()
            
            if command == 'start':
                if not running:
                    start_all_services()
                else:
                    print("服务已在运行中")
                    
            elif command == 'stop':
                if running:
                    stop_all_services()
                else:
                    print("服务未运行")
                    
            elif command == 'restart':
                restart_all_services()
                
            elif command == 'status':
                show_status()
                
            elif command == 'exit':
                print("正在退出...")
                stop_all_services()
                break
                
            elif command == 'help':
                print("\n可用命令:")
                print("  start  - 启动所有服务")
                print("  stop   - 停止所有服务")
                print("  restart- 重启所有服务")
                print("  status - 显示系统状态")
                print("  exit   - 退出程序")
                print("  help   - 显示此帮助信息")
                
            elif command == '':
                continue
                
            else:
                print(f"未知命令: {command},输入 'help' 查看可用命令")
                
        except KeyboardInterrupt:
            print("\n接收到中断信号,正在退出...")
            stop_all_services()
            break
        except EOFError:
            print("\n输入结束,正在退出...")
            stop_all_services()
            break
        except Exception as e:
            print(f"处理命令时出错: {e}")

def main():
    """
    主函数
    """
    # 注册信号处理器
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    print("eman_one 同步版本")
    print(f"Python版本: {sys.version}")
    print(f"工作目录: {os.getcwd()}")
    
    # 检查启动模式
    mode = 'common'  # 默认模式
    if len(sys.argv) > 1:
        mode = sys.argv[1].lower()
    
    if mode == 'web':
        # Web模式:只启动服务,不启动控制台监听
        print("\n启动模式: Web")
        if start_all_services():
            print("\nWeb模式启动成功,服务将持续运行...")
            try:
                # 保持主线程运行
                while running:
                    time.sleep(1)
            except KeyboardInterrupt:
                print("\n接收到中断信号")
            finally:
                stop_all_services()
        else:
            print("Web模式启动失败")
            sys.exit(1)
    else:
        # 普通模式:启动服务并启动控制台监听
        print("\n启动模式: 普通模式")
        
        # 自动启动服务
        start_all_services()
        
        # 启动控制台监听
        try:
            console_input_listener()
        except Exception as e:
            print(f"控制台监听出错: {e}")
        finally:
            stop_all_services()
    
    print("程序已退出")

if __name__ == "__main__":
    main()