diff --git a/dsLightRag/Config/Config.py b/dsLightRag/Config/Config.py index 2d086f05..988004bc 100644 --- a/dsLightRag/Config/Config.py +++ b/dsLightRag/Config/Config.py @@ -3,8 +3,8 @@ ES_CONFIG = { 'hosts': ['https://localhost:9200'], 'basic_auth': ('elastic', 'jv9h8uwRrRxmDi1dq6u8'), 'verify_certs': False, - 'index_name': 'ds_db', # 默认索引名称 - 'student_info_index': 'student_info' # 添加student_info索引名称配置 + 'index_name': 'ds_db', # 默认索引名称 + 'student_info_index': 'student_info' # 添加student_info索引名称配置 } # 阿里云的配置信息【绘智科技】 @@ -51,13 +51,12 @@ GLM_BASE_URL = "https://api.siliconflow.cn/v1/chat/completions" GLM_API_KEY = "sk-pbqibyjwhrgmnlsmdygplahextfaclgnedetybccknxojlyl" GLM_MODEL_NAME = "THUDM/GLM-4.1V-9B-Thinking" - # 阿里云API信息【YLT】 -#ALY_LLM_API_KEY = "sk-f6da0c787eff4b0389e4ad03a35a911f" +# ALY_LLM_API_KEY = "sk-f6da0c787eff4b0389e4ad03a35a911f" # 阿里云API信息【绘智科技】 ALY_LLM_API_KEY = "sk-01d13a39e09844038322108ecdbd1bbc" ALY_LLM_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1" -#ALY_LLM_MODEL_NAME = "deepseek-r1" +# ALY_LLM_MODEL_NAME = "deepseek-r1" ALY_LLM_MODEL_NAME = "qwen-plus" # ALY_LLM_MODEL_NAME = "deepseek-v3" @@ -73,7 +72,7 @@ ZHIPU_API_KEY = "78dc1dfe37e04f29bd4ca9a49858a969.gn7TIZTfzpY35nx9" # GPTNB的API KEY GPTNB_API_KEY = "sk-amQHwiEzPIZIB2KuF5A10dC23a0e4b02B48a7a2b6aFa0662" -GPTNB_BASE_URL="https://goapi.gptnb.ai" +GPTNB_BASE_URL = "https://goapi.gptnb.ai" # JWT配置信息 JWT_SECRET_KEY = "ZXZnZWVr5b+r5LmQ5L2g55qE5Ye66KGM" @@ -82,7 +81,10 @@ ACCESS_TOKEN_EXPIRE_MINUTES = 300000 # 访问令牌过期时间(分钟) # 火山引擎相关信息 # 语音识别 https://console.volcengine.com/speech/service/10012?AppID=1513532196 -HS_APP_ID= "1513532196" -HS_ACCESS_TOKEN= "ti2NW-kbjIbkzc6BK55actnI_wTR8xkH" -HS_CLUSTER_ID="volcano_tts" -HS_VOICE_TYPE = "zh_female_wanwanxiaohe_moon_bigtts" # 中文女声 湾湾小何 +HS_APP_ID = "1513532196" +HS_ACCESS_TOKEN = "ti2NW-kbjIbkzc6BK55actnI_wTR8xkH" +HS_CLUSTER_ID = "volcano_tts" +# 音色列表:https://www.volcengine.com/docs/6561/97465 +# 音色体验:https://www.volcengine.com/product/tts +HS_VOICE_TYPE = "zh_female_wanwanxiaohe_moon_bigtts" # 中文女声 湾湾小何 +HS_VOICE_TYPE_QINCANG = "BV701_V2_streaming" # 中年男声,用于朗读古诗 diff --git a/dsLightRag/Config/__pycache__/Config.cpython-310.pyc b/dsLightRag/Config/__pycache__/Config.cpython-310.pyc index ea70d283..f75b2362 100644 Binary files a/dsLightRag/Config/__pycache__/Config.cpython-310.pyc and b/dsLightRag/Config/__pycache__/Config.cpython-310.pyc differ diff --git a/dsLightRag/Test/GengerateAudio.py b/dsLightRag/Test/GengerateAudio.py new file mode 100644 index 00000000..8285f645 --- /dev/null +++ b/dsLightRag/Test/GengerateAudio.py @@ -0,0 +1,73 @@ +#coding=utf-8 + +''' +requires Python 3.6 or later +pip install requests +''' +import base64 +import json +import uuid +import requests + +from Config.Config import HS_APP_ID, HS_ACCESS_TOKEN, HS_CLUSTER_ID, HS_VOICE_TYPE_QINCANG + +# 填写平台申请的appid, access_token以及cluster +appid = HS_APP_ID +access_token= HS_ACCESS_TOKEN +cluster = HS_CLUSTER_ID + +voice_type = HS_VOICE_TYPE_QINCANG +host = "openspeech.bytedance.com" +api_url = f"https://{host}/api/v1/tts" + +header = {"Authorization": f"Bearer;{access_token}"} + +request_json = { + "app": { + "appid": appid, + "token": "access_token", + "cluster": cluster + }, + "user": { + "uid": "388808087185088" + }, + "audio": { + "voice_type": voice_type, + "encoding": "mp3", + "speed_ratio": 1.0, + "volume_ratio": 1.0, + "pitch_ratio": 1.0, + }, + "request": { + "reqid": str(uuid.uuid4()), + "text": """ + 君不见,黄河之水天上来,奔流到海不复回。 + 君不见,高堂明镜悲白发,朝如青丝暮成雪。 + 人生得意须尽欢,莫使金樽空对月。 + 天生我材必有用,千金散尽还复来。 + 烹羊宰牛且为乐,会须一饮三百杯。 + 岑夫子,丹丘生,将进酒,杯莫停。 + 与君歌一曲,请君为我倾耳听。 + 钟鼓馔玉不足贵,但愿长醉不复醒。 + 古来圣贤皆寂寞,惟有饮者留其名。 + 陈王昔时宴平乐,斗酒十千恣欢谑。 + 主人何为言少钱,径须沽取对君酌。 + 五花马,千金裘,呼儿将出换美酒,与尔同销万古愁。 + """, + "text_type": "plain", + "operation": "query", + "with_frontend": 1, + "frontend_type": "unitTson" + } +} + +if __name__ == '__main__': + try: + resp = requests.post(api_url, json.dumps(request_json), headers=header) + #print(f"resp body: \n{resp.json()}") + if "data" in resp.json(): + data = resp.json()["data"] + file_to_save = open("test_submit.mp3", "wb") + file_to_save.write(base64.b64decode(data)) + except Exception as e: + e.with_traceback() diff --git a/dsLightRag/Test/JiangJinJiu.mp3 b/dsLightRag/Test/JiangJinJiu.mp3 new file mode 100644 index 00000000..24b2e49f Binary files /dev/null and b/dsLightRag/Test/JiangJinJiu.mp3 differ diff --git a/dsLightRag/Test/VideoRetalk.py b/dsLightRag/Test/VideoRetalk.py new file mode 100644 index 00000000..0771e751 --- /dev/null +++ b/dsLightRag/Test/VideoRetalk.py @@ -0,0 +1,211 @@ +import requests +import time +from typing import Dict, Optional + +from Config import Config + + +class VideoRetalk: + """ + 阿里云DashScope LivePortrait视频生成类 + videoretalk是一个人物视频生成模型,可基于人物视频和人声音频,生成人物讲话口型与输入音频相匹配的新视频。 + 视频口型替换-声动人像VideoRetalk + 实现图像和音频合成视频功能 + """ + + def __init__(self, api_key: str): + """ + 初始化视频生成类 + + Args: + api_key: 阿里云DashScope API密钥 + """ + self.api_key = api_key + self.base_url = "https://dashscope.aliyuncs.com/api/v1" + self.video_synthesis_url = f"{self.base_url}/services/aigc/image2video/video-synthesis" + + def submit_video_task(self, image_url: str, audio_url: str, + template_id: str = "normal", + eye_move_freq: float = 0.5, + video_fps: int = 30, + mouth_move_strength: float = 1.0, + paste_back: bool = True, + head_move_strength: float = 0.7) -> Dict: + """ + 提交视频生成任务 + + Args: + image_url: 输入图片URL + audio_url: 输入音频URL + template_id: 模板ID,默认为"normal" + eye_move_freq: 眼睛移动频率,默认0.5 + video_fps: 视频帧率,默认30 + mouth_move_strength: 嘴巴移动强度,默认1.0 + paste_back: 是否粘贴背景,默认True + head_move_strength: 头部移动强度,默认0.7 + + Returns: + Dict: 包含task_id和task_status的响应数据 + """ + headers = { + 'X-DashScope-Async': 'enable', + 'Authorization': f'Bearer {self.api_key}', + 'Content-Type': 'application/json' + } + + payload = { + "model": "liveportrait", + "input": { + "image_url": image_url, + "audio_url": audio_url + }, + "parameters": { + "template_id": template_id, + "eye_move_freq": eye_move_freq, + "video_fps": video_fps, + "mouth_move_strength": mouth_move_strength, + "paste_back": paste_back, + "head_move_strength": head_move_strength + } + } + + try: + response = requests.post(self.video_synthesis_url, + headers=headers, + json=payload) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + raise Exception(f"提交视频任务失败: {e}") + + def get_task_status(self, task_id: str) -> Dict: + """ + 查询任务状态 + + Args: + task_id: 任务ID + + Returns: + Dict: 任务状态信息 + """ + headers = { + 'Authorization': f'Bearer {self.api_key}' + } + + task_url = f"{self.base_url}/tasks/{task_id}" + + try: + response = requests.get(task_url, headers=headers) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + raise Exception(f"查询任务状态失败: {e}") + + def wait_for_task_completion(self, task_id: str, + poll_interval: int = 5, + timeout: int = 300) -> Dict: + """ + 等待任务完成 + + Args: + task_id: 任务ID + poll_interval: 轮询间隔(秒),默认5秒 + timeout: 超时时间(秒),默认300秒 + + Returns: + Dict: 任务完成后的结果 + """ + start_time = time.time() + + while time.time() - start_time < timeout: + task_status = self.get_task_status(task_id) + + status = task_status.get('output', {}).get('task_status') + + if status == 'SUCCEEDED': + return task_status + elif status == 'FAILED': + error_code = task_status.get('output', {}).get('code', '未知错误') + error_message = task_status.get('output', {}).get('message', '无错误信息') + raise Exception(f"任务执行失败: {error_code} - {error_message}") + elif status in ['PENDING', 'RUNNING']: + print(f"任务状态: {status}, 等待中...") + time.sleep(poll_interval) + else: + raise Exception(f"未知的任务状态: {status}") + + raise Exception(f"任务超时,未在{timeout}秒内完成") + + def generate_video(self, image_url: str, audio_url: str, + **kwargs) -> Optional[str]: + """ + 生成视频的完整流程 + + Args: + image_url: 输入图片URL + audio_url: 输入音频URL + **kwargs: 其他参数,同submit_video_task + + Returns: + str: 生成的视频URL,失败返回None + """ + try: + # 提交任务 + submit_response = self.submit_video_task(image_url, audio_url, **kwargs) + task_id = submit_response.get('output', {}).get('task_id') + + if not task_id: + print("提交任务失败,未获取到task_id") + return None + + print(f"任务已提交,task_id: {task_id}") + + # 等待任务完成 + result = self.wait_for_task_completion(task_id) + + # 获取视频URL + video_url = result.get('output', {}).get('results', {}).get('video_url') + + if video_url: + print(f"视频生成成功: {video_url}") + # 获取使用情况信息 + usage = result.get('usage', {}) + if usage: + print(f"视频时长: {usage.get('video_duration')}秒") + print(f"视频比例: {usage.get('video_ratio')}") + return video_url + else: + print("未找到生成的视频URL") + return None + + except Exception as e: + print(f"视频生成失败: {e}") + return None + + +# 使用示例 +if __name__ == "__main__": + # 替换为您的实际API密钥 + API_KEY = Config.ALY_LLM_API_KEY + + # 创建视频生成实例 + video_retalk = VideoRetalk(API_KEY) + + # 示例:生成视频 + try: + video_url = video_retalk.generate_video( + image_url="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/LiBai.jpg", + audio_url="https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Backup/JiangJinJiu.mp3", + template_id="normal", + eye_move_freq=0.5, + video_fps=30, + mouth_move_strength=1.0, + paste_back=True, + head_move_strength=0.7 + ) + + if video_url: + print(f"最终视频URL: {video_url}") + + except Exception as e: + print(f"执行过程中发生错误: {e}") \ No newline at end of file