118 lines
6.6 KiB
Python
Raw Permalink Normal View History

2025-09-05 14:41:59 +08:00
# ------------
# 导入所需模块和函数
# ------------
import json # 导入JSON处理模块
import os # 导入操作系统模块
from core.utils import * # 导入核心工具函数
try:
from core.asr_backend.demucs_vl import demucs_audio # 导入Demucs音频分离功能可选
except ImportError:
demucs_audio = None # Demucs不可用时的占位符
from core.asr_backend.audio_preprocess import process_transcription, convert_video_to_audio, split_audio, save_results, normalize_audio_volume # 导入音频预处理相关函数
# 重构后删除了ytdlp模块视频文件路径由主程序提供
# from core._1_ytdlp import find_video_files
from core.utils.models import * # 导入模型相关工具
2025-08-20 11:39:34 +08:00
2025-09-05 14:41:59 +08:00
# ------------
# 音频转录主函数
# ------------
@check_file_exists(_2_CLEANED_CHUNKS) # 检查清理后的音频片段文件是否存在的装饰器
2025-08-20 11:39:34 +08:00
def transcribe():
2025-09-05 14:41:59 +08:00
# ------------
# 步骤1: 视频转音频
# ------------
# 重构后由主程序保证视频文件在output目录下
video_files = [f for f in os.listdir('output') if f.endswith(('.mp4', '.avi', '.mov', '.mkv'))]
if not video_files:
raise FileNotFoundError("在output目录下没有找到视频文件")
video_file = os.path.join('output', video_files[0]) # 使用第一个找到的视频文件
convert_video_to_audio(video_file) # 将视频文件转换为音频文件
2025-08-20 11:39:34 +08:00
2025-09-05 14:41:59 +08:00
# ------------
# 步骤2: Demucs人声分离
# ------------
if load_key("demucs") and demucs_audio is not None: # 检查是否启用Demucs音频分离且模块可用
demucs_audio() # 执行音频分离,提取人声
vocal_audio = normalize_audio_volume(_VOCAL_AUDIO_FILE, _VOCAL_AUDIO_FILE, format="mp3") # 标准化人声音频音量
2025-08-20 11:39:34 +08:00
else:
2025-09-05 14:41:59 +08:00
vocal_audio = _RAW_AUDIO_FILE # 如果未启用分离或模块不可用,直接使用原始音频文件
2025-08-20 11:39:34 +08:00
2025-09-05 14:41:59 +08:00
# ------------
# 步骤3: 音频分割
# ------------
segments = split_audio(_RAW_AUDIO_FILE) # 将音频文件分割成多个时间段
# ------------
# 步骤4: 按片段转录音频
# ------------
all_results = [] # 初始化结果列表存储所有转录结果
runtime = load_key("whisper.runtime") # 获取whisper运行时配置
if runtime == "local": # 如果使用本地模型
from core.asr_backend.whisperX_local import transcribe_audio as ts # 导入本地转录函数
rprint("[cyan]🎤 Transcribing audio with local model...[/cyan]") # 打印本地模型转录提示
elif runtime == "cloud": # 如果使用云端API
from core.asr_backend.whisperX_302 import transcribe_audio_302 as ts # 导入302云端转录函数
rprint("[cyan]🎤 Transcribing audio with 302 API...[/cyan]") # 打印云端API转录提示
elif runtime == "elevenlabs": # 如果使用ElevenLabs API
from core.asr_backend.elevenlabs_asr import transcribe_audio_elevenlabs as ts # 导入ElevenLabs转录函数
rprint("[cyan]🎤 Transcribing audio with ElevenLabs API...[/cyan]") # 打印ElevenLabs API转录提示
for start, end in segments: # 遍历每个音频片段的开始和结束时间
result = ts(_RAW_AUDIO_FILE, vocal_audio, start, end) # 对当前片段进行转录
all_results.append(result) # 将转录结果添加到结果列表
# ------------
# 步骤5: 合并转录结果
# ------------
combined_result = {'segments': []} # 初始化合并结果字典
for result in all_results: # 遍历所有转录结果
combined_result['segments'].extend(result['segments']) # 将每个结果的segments部分合并到总结果中
# ------------
# 步骤6: 处理和保存结果
# ------------
df = process_transcription(combined_result) # 将合并后的转录结果处理成DataFrame格式
save_results(df) # 保存处理后的转录结果到文件
# # ------------
# # 步骤7: 保存标准化的JSON格式结果用于语义切割模块
# # ------------
# save_asr_result_json(combined_result) # 保存符合重构标准的JSON格式结果
2025-08-20 11:39:34 +08:00
2025-09-05 14:41:59 +08:00
# ------------
# 新增函数保存标准化的ASR结果为JSON格式
# ------------
# def save_asr_result_json(transcription_result):
# """
# 将ASR转录结果保存为标准化的JSON格式
# Args:
# transcription_result: Whisper转录的原始结果包含segments列表
# """
# asr_result = []
# # 遍历所有segments提取文本和时间戳信息
# for i, segment in enumerate(transcription_result.get('segments', [])):
# # 提取基本信息
# text = segment.get('text', '').strip()
# start = float(segment.get('start', 0))
# end = float(segment.get('end', 0))
# # 过滤掉空文本的片段
# if text:
# asr_result.append({
# "id": i,
# "text": text,
# "start": start,
# "end": end
# })
# # 保存到JSON文件
# os.makedirs('output', exist_ok=True)
# with open(_ASR_RESULT, 'w', encoding='utf-8') as f:
# json.dump(asr_result, f, ensure_ascii=False, indent=2)
# rprint(f"[green]📄 ASR result saved to {_ASR_RESULT} with {len(asr_result)} segments[/green]")
2025-08-20 11:39:34 +08:00
2025-09-05 14:41:59 +08:00
if __name__ == "__main__": # 主程序入口
transcribe() # 执行转录函数