You've already forked FrameTour-RenderWorker
feat(base): 添加单任务内文件传输并发功能
- 引入 ThreadPoolExecutor 实现并行下载和上传 - 新增 download_files_parallel 和 upload_files_parallel 方法 - 添加任务传输并发数配置选项 TASK_DOWNLOAD_CONCURRENCY 和 TASK_UPLOAD_CONCURRENCY - 实现并发数配置的环境变量解析和验证逻辑 - 在多个处理器中应用并行下载优化文件获取性能 - 更新 .env.example 配置文件模板 - 移除 FFmpeg 命令日志长度限制
This commit is contained in:
@@ -55,32 +55,60 @@ class PrepareJobAudioHandler(BaseHandler):
|
||||
bgm_url = task.get_bgm_url()
|
||||
segments = task.get_segments()
|
||||
|
||||
# 1. 下载 BGM(如有)
|
||||
bgm_file = None
|
||||
# 1. 并行下载 BGM 与叠加音效
|
||||
bgm_file = os.path.join(work_dir, 'bgm.mp3') if bgm_url else None
|
||||
download_jobs = []
|
||||
if bgm_url and bgm_file:
|
||||
download_jobs.append({
|
||||
'key': 'bgm',
|
||||
'url': bgm_url,
|
||||
'dest': bgm_file,
|
||||
'required': False
|
||||
})
|
||||
|
||||
sfx_download_candidates = []
|
||||
for i, seg in enumerate(segments):
|
||||
audio_spec_data = seg.get('audioSpecJson')
|
||||
if not audio_spec_data:
|
||||
continue
|
||||
audio_spec = AudioSpec.from_dict(audio_spec_data)
|
||||
if not audio_spec or not audio_spec.audio_url:
|
||||
continue
|
||||
sfx_file = os.path.join(work_dir, f'sfx_{i}.mp3')
|
||||
job_key = f'sfx_{i}'
|
||||
sfx_download_candidates.append({
|
||||
'key': job_key,
|
||||
'file': sfx_file,
|
||||
'spec': audio_spec,
|
||||
'segment': seg
|
||||
})
|
||||
download_jobs.append({
|
||||
'key': job_key,
|
||||
'url': audio_spec.audio_url,
|
||||
'dest': sfx_file,
|
||||
'required': False
|
||||
})
|
||||
|
||||
download_results = self.download_files_parallel(download_jobs)
|
||||
if bgm_url:
|
||||
bgm_file = os.path.join(work_dir, 'bgm.mp3')
|
||||
if not self.download_file(bgm_url, bgm_file):
|
||||
bgm_result = download_results.get('bgm')
|
||||
if not bgm_result or not bgm_result['success']:
|
||||
logger.warning(f"[task:{task.task_id}] Failed to download BGM")
|
||||
bgm_file = None
|
||||
|
||||
# 2. 下载叠加音效
|
||||
sfx_files = []
|
||||
for i, seg in enumerate(segments):
|
||||
audio_spec_data = seg.get('audioSpecJson')
|
||||
if audio_spec_data:
|
||||
audio_spec = AudioSpec.from_dict(audio_spec_data)
|
||||
if audio_spec and audio_spec.audio_url:
|
||||
sfx_file = os.path.join(work_dir, f'sfx_{i}.mp3')
|
||||
if self.download_file(audio_spec.audio_url, sfx_file):
|
||||
sfx_files.append({
|
||||
'file': sfx_file,
|
||||
'spec': audio_spec,
|
||||
'segment': seg
|
||||
})
|
||||
else:
|
||||
logger.warning(f"[task:{task.task_id}] Failed to download SFX {i}")
|
||||
for sfx_candidate in sfx_download_candidates:
|
||||
sfx_result = download_results.get(sfx_candidate['key'])
|
||||
if sfx_result and sfx_result['success']:
|
||||
sfx_files.append({
|
||||
'file': sfx_candidate['file'],
|
||||
'spec': sfx_candidate['spec'],
|
||||
'segment': sfx_candidate['segment']
|
||||
})
|
||||
else:
|
||||
logger.warning(f"[task:{task.task_id}] Failed to download SFX {sfx_candidate['key']}")
|
||||
|
||||
# 3. 构建音频混音命令
|
||||
# 2. 构建音频混音命令
|
||||
output_file = os.path.join(work_dir, 'audio_full.aac')
|
||||
cmd = self._build_audio_command(
|
||||
bgm_file=bgm_file,
|
||||
@@ -90,21 +118,21 @@ class PrepareJobAudioHandler(BaseHandler):
|
||||
audio_profile=audio_profile
|
||||
)
|
||||
|
||||
# 4. 执行 FFmpeg
|
||||
# 3. 执行 FFmpeg
|
||||
if not self.run_ffmpeg(cmd, task.task_id):
|
||||
return TaskResult.fail(
|
||||
ErrorCode.E_FFMPEG_FAILED,
|
||||
"Audio mixing failed"
|
||||
)
|
||||
|
||||
# 5. 验证输出文件
|
||||
# 4. 验证输出文件
|
||||
if not self.ensure_file_exists(output_file, min_size=1024):
|
||||
return TaskResult.fail(
|
||||
ErrorCode.E_FFMPEG_FAILED,
|
||||
"Audio output file is missing or too small"
|
||||
)
|
||||
|
||||
# 6. 上传产物
|
||||
# 5. 上传产物
|
||||
audio_url = self.upload_file(task.task_id, 'audio', output_file)
|
||||
if not audio_url:
|
||||
return TaskResult.fail(
|
||||
|
||||
Reference in New Issue
Block a user