busy & happy

忙碌日常与紫金山之旅
最近实在是懒得写spaces了。马上去开项目会了,还有十分钟无聊,写点吧。

现在手头有4个项目,1个毕论的任务。简直不是人过的日子啊。加上3月底已经干了一个月的活,实在有点吃不消了。上个周日第一次去爬了紫金山,来南京四年第一次上山顶,以前去过两次,中山植物园和中山陵,都没上去山顶-头陀岭。和LP很久没出去玩了,觉得出去晒晒太阳还是很好的~下次再去别的地方玩,呵呵~

马上开会了。。
from pathlib import Path from openai import OpenAI, OpenAIError import logging from api.config import API_CONFIGS import os import pygame import time class VoiceManager: """ 语音管理类,通过阶跃星辰API实现文本转语音功能 """ def __init__(self): """ 初始化语音管理器,从config.py加载API配置 """ self.logger = logging.getLogger(__name__) try: step_config = API_CONFIGS['step_tts'] self._validate_config(step_config) self.client = OpenAI( api_key=step_config['key'], base_url=step_config['endpoint'] ) self.logger.info("VoiceManager initialized successfully") except KeyError as e: self.logger.error(f"Missing required config: {e}") raise except Exception as e: self.logger.error(f"Initialization failed: {e}") raise def _play_audio_file(self, audio_file_path): """播放音频文件""" try: import pygame pygame.mixer.init() pygame.mixer.music.load(str(audio_file_path)) pygame.mixer.music.play() # 等待播放完成 while pygame.mixer.music.get_busy(): pygame.time.Clock().tick(10) except pygame.error as e: self.logger.error(f"Pygame audio error: {e}") raise except Exception as e: self.logger.error(f"Unexpected error during audio playback: {e}") raise finally: # 确保资源被释放 pygame.mixer.quit() def _validate_config(self, config): """ 验证配置完整性 :param config: API配置字典 :raises: ValueError 如果缺少必要配置项 """ required_keys = ['key', 'endpoint', 'default_model'] for key in required_keys: if key not in config: raise ValueError(f"Missing required config key: {key}") def create_voice(self, text, voice=None, language=None, emotion=None, style=None, play_immediately=False): """ 创建语音文件并可选直接播放 :param text: 要合成的文本 :param voice: 音色名称(默认使用config中的配置) :param language: 语言(默认使用config中的配置) :param emotion: 情感(默认使用config中的配置) :param style: 语速风格(默认使用config中的配置) :param play_immediately: 是否立即播放语音 :return: 生成的语音文件路径 :raises: ValueError 如果输入文本为空 :raises: OpenAIError 如果API调用失败 """ if not text: raise ValueError("Text cannot be empty") try: speech_file = Path(__file__).parent / "generated_voice.mp3" step_config = API_CONFIGS['step_tts'] self.logger.info(f"Creating voice for text: {text[:50]}...") response = self.client.audio.speech.create( model=step_config['default_model'], input=text, voice=voice or step_config['default_voice'], response_format="mp3", speed=1.0, extra_body={ "language": language or step_config['voice_options']['language'], "emotion": emotion or step_config['voice_options']['emotion'], "style": style or step_config['voice_options']['style'], "volume": 1.0 } ) self._handle_response(response, speech_file) self.logger.info(f"Voice file created at: {speech_file}") if play_immediately: self._play_audio_file(speech_file) return speech_file except OpenAIError as e: self.logger.error(f"OpenAI API error: {e}") raise except Exception as e: self.logger.error(f"Error creating voice: {e}") raise def _handle_response(self, response, output_file): """ Handle the streaming response and save to file. """ try: response.stream_to_file(output_file) except Exception as e: self.logger.error(f"Error handling response: {str(e)}") raise def cleanup(self, keep_latest=3): """清理旧语音文件""" voice_files = sorted(Path(__file__).parent.glob('*.mp3'), key=os.path.getmtime) for old_file in voice_files[:-keep_latest]: old_file.unlink() @classmethod def check_api_status(cls): """检查API连通性""" try: cls().create_voice("测试连接") return True except Exception: return False def reload_config(self): """热加载API配置""" from importlib import reload from api import config reload(config) self.__init__() if __name__ == "__main__": manager = VoiceManager() manager.create_voice("测试文本") PRESETS = { 'happy': {'emotion': '高兴', 'style': '活泼'}, 'formal': {'emotion': '中性', 'style': '标准'} } def create_voice_with_preset(self, text, preset_name): """使用预设参数创建语音""" return self.create_voice(text, **self.PRESETS.get(preset_name, {})) 能正常运行但是无法直接播放音频,需要手动播放,在源代码的基础上实现自动播放得到的音频文件
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值