From 8b5ff0658b17a6f5d8a5f8dc460cb7431b186916 Mon Sep 17 00:00:00 2001 From: linyq Date: Wed, 7 May 2025 00:59:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(task):=20=E4=BC=98=E5=8C=96=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E6=97=B6=E9=97=B4=E6=88=B3=E6=9B=B4=E6=96=B0=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E5=B9=B6=E6=B7=BB=E5=8A=A0=E9=9F=B3=E9=A2=91=E8=B7=AF?= =?UTF-8?q?=E5=BE=84-=20=E4=BF=AE=E6=94=B9=20update=5Fscript=5Ftimestamps?= =?UTF-8?q?=20=E5=87=BD=E6=95=B0=EF=BC=8C=E6=94=AF=E6=8C=81=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E6=9B=B4=E6=96=B0=E8=A7=86=E9=A2=91=E5=92=8C=E9=9F=B3?= =?UTF-8?q?=E9=A2=91=E8=B7=AF=E5=BE=84=20-=20=E5=9C=A8=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=A4=84=E7=90=86=E6=B5=81=E7=A8=8B=E4=B8=AD=E7=94=9F=E6=88=90?= =?UTF-8?q?=20tts=5Fclip=5Fresult=20=E5=AD=97=E5=85=B8=EF=BC=8C=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E6=9B=B4=E6=96=B0=E8=84=9A=E6=9C=AC=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E9=9F=B3=E9=A2=91=E8=B7=AF=E5=BE=84=20-=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=88=97=E8=A1=A8=E7=9A=84=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E7=A1=AE=E4=BF=9D=E6=89=80=E6=9C=89?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=88=B3=E9=83=BD=E8=AE=A1=E7=AE=97=E6=8C=81?= =?UTF-8?q?=E7=BB=AD=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/task.py | 4 +- app/services/update_script.py | 69 ++++++++++++++++++++++------------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/app/services/task.py b/app/services/task.py index ae2ea29..42853f2 100644 --- a/app/services/task.py +++ b/app/services/task.py @@ -248,7 +248,8 @@ def start_subclip(task_id: str, params: VideoClipParams, subclip_path_videos: di clip_result = clip_video.clip_video(params.video_origin_path, tts_results) subclip_path_videos.update(clip_result) # 更新 list_script 中的时间戳 - list_script = update_script.update_script_timestamps(list_script, clip_result) + tts_clip_result = {tts_result['timestamp']: tts_result['audio_file'] for tts_result in tts_results} + list_script = update_script.update_script_timestamps(list_script, clip_result, tts_clip_result) subclip_videos = [x for x in subclip_path_videos.values()] sm.state.update_task(task_id, state=const.TASK_STATE_PROCESSING, progress=60) @@ -257,7 +258,6 @@ def start_subclip(task_id: str, params: VideoClipParams, subclip_path_videos: di 4. 合并音频和字幕 """ logger.info("\n\n## 4. 合并音频和字幕") - subtitle_files = [ tts_result["subtitle_file"] for tts_result in tts_results ] diff --git a/app/services/update_script.py b/app/services/update_script.py index 5dd10a9..3213b6d 100644 --- a/app/services/update_script.py +++ b/app/services/update_script.py @@ -26,13 +26,13 @@ def extract_timestamp_from_video_path(video_path: str) -> str: # 使用正则表达式从文件名中提取时间戳 filename = os.path.basename(video_path) match = re.search(r'vid-(\d{2}-\d{2}-\d{2})-(\d{2}-\d{2}-\d{2})\.mp4', filename) - + if match: # 提取并格式化时间戳 start_time = match.group(1).replace('-', ':') end_time = match.group(2).replace('-', ':') return f"{start_time}-{end_time}" - + return "" @@ -48,58 +48,69 @@ def calculate_duration(timestamp: str) -> float: """ try: start_time, end_time = timestamp.split('-') - + # 解析时间 start_h, start_m, start_s = map(int, start_time.split(':')) end_h, end_m, end_s = map(int, end_time.split(':')) - + # 转换为秒 start_seconds = start_h * 3600 + start_m * 60 + start_s end_seconds = end_h * 3600 + end_m * 60 + end_s - + # 计算时间差(秒) return round(end_seconds - start_seconds, 2) except (ValueError, AttributeError): return 0.0 -def update_script_timestamps(script_list: List[Dict[str, Any]], tts_result: Dict[str, str]) -> List[Dict[str, Any]]: +def update_script_timestamps(script_list: List[Dict[str, Any]], video_result: Dict[str, str], audio_result: Dict[str, str] = None) -> List[Dict[str, Any]]: """ - 根据 tts_res 中的视频文件更新 list_script 中的时间戳,并添加持续时间 + 根据 video_result 中的视频文件更新 script_list 中的时间戳,添加持续时间,并根据 audio_result 添加音频路径 Args: script_list: 原始脚本列表 - tts_result: TTS 结果字典,键为原时间戳,值为视频文件路径 + video_result: 视频结果字典,键为原时间戳,值为视频文件路径 + audio_result: 音频结果字典,键为原时间戳,值为音频文件路径 Returns: 更新后的脚本列表 """ # 创建副本,避免修改原始数据 updated_script = [] - - # 建立原始时间戳到新时间戳的映射 + + # 建立原始时间戳到视频路径和新时间戳的映射 timestamp_mapping = {} - for orig_timestamp, video_path in tts_result.items(): + for orig_timestamp, video_path in video_result.items(): new_timestamp = extract_timestamp_from_video_path(video_path) if new_timestamp: - timestamp_mapping[orig_timestamp] = new_timestamp - + timestamp_mapping[orig_timestamp] = { + 'new_timestamp': new_timestamp, + 'video_path': video_path + } + # 更新脚本中的时间戳 for item in script_list: item_copy = item.copy() - if item_copy.get('timestamp') in timestamp_mapping: + orig_timestamp = item_copy.get('timestamp', '') + + # 初始化音频路径为空字符串 + item_copy['audio'] = "" + + # 如果提供了音频结果字典且时间戳存在于音频结果中,直接使用对应的音频路径 + if audio_result and orig_timestamp in audio_result: + item_copy['audio'] = audio_result[orig_timestamp] + + if orig_timestamp in timestamp_mapping: # 更新时间戳 - new_timestamp = timestamp_mapping[item_copy['timestamp']] - item_copy['timestamp'] = new_timestamp - - # 计算并添加持续时间 - item_copy['duration'] = calculate_duration(new_timestamp) - elif 'timestamp' in item_copy: - # 对于未更新的时间戳,也计算并添加持续时间 + item_copy['timestamp'] = timestamp_mapping[orig_timestamp]['new_timestamp'] + # 计算持续时间 item_copy['duration'] = calculate_duration(item_copy['timestamp']) - + elif orig_timestamp: + # 对于未更新的时间戳,也计算并添加持续时间 + item_copy['duration'] = calculate_duration(orig_timestamp) + updated_script.append(item_copy) - + return updated_script @@ -122,13 +133,19 @@ if __name__ == '__main__': 'narration': '但想见庆帝,哪有那么容易?范闲艺高人胆大,竟然选择了最激进的方式——闯宫!', 'OST': 0}, {'picture': '画面切换到范闲蒙面闯入皇宫,被侍卫包围的场景。', 'timestamp': '00:06:00-00:06:03', 'narration': '抓刺客', 'OST': 1}] - tts_res = { + video_res = { '00:00:00-00:01:15': '/Users/apple/Desktop/home/NarratoAI/storage/temp/clip_video/0ac14d474144b54d614c26a5c87cffe7/vid-00-00-00-00-00-26.mp4', '00:01:15-00:04:40': '/Users/apple/Desktop/home/NarratoAI/storage/temp/clip_video/0ac14d474144b54d614c26a5c87cffe7/vid-00-01-15-00-01-29.mp4', '00:04:58-00:05:45': '/Users/apple/Desktop/home/NarratoAI/storage/temp/clip_video/0ac14d474144b54d614c26a5c87cffe7/vid-00-04-58-00-05-20.mp4', '00:05:45-00:06:00': '/Users/apple/Desktop/home/NarratoAI/storage/temp/clip_video/0ac14d474144b54d614c26a5c87cffe7/vid-00-05-45-00-05-53.mp4'} + audio_res = { + '00:00:00-00:01:15': '/Users/apple/Desktop/home/NarratoAI/storage/tasks/qyn2-2-demo/audio_00_00_00-00_01_15.mp3', + '00:01:15-00:04:40': '/Users/apple/Desktop/home/NarratoAI/storage/tasks/qyn2-2-demo/audio_00_01_15-00_04_40.mp3', + '00:04:58-00:05:45': '/Users/apple/Desktop/home/NarratoAI/storage/tasks/qyn2-2-demo/audio_00_04_58-00_05_45.mp3', + '00:05:45-00:06:00': '/Users/apple/Desktop/home/NarratoAI/storage/tasks/qyn2-2-demo/audio_00_05_45-00_06_00.mp3'} # 更新并打印结果 - updated_list_script = update_script_timestamps(list_script, tts_res) + updated_list_script = update_script_timestamps(list_script, video_res, audio_res) for item in updated_list_script: - print(f"Picture: {item['picture'][:20]}... | Timestamp: {item['timestamp']} | Duration: {item['duration']} 秒") + print( + f"Picture: {item['picture'][:20]}... | Timestamp: {item['timestamp']} | Duration: {item['duration']} 秒 | Audio: {item['audio']}")