118 lines
6.6 KiB
Python
118 lines
6.6 KiB
Python
# ------------
|
||
# 导入所需模块和函数
|
||
# ------------
|
||
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 * # 导入模型相关工具
|
||
|
||
# ------------
|
||
# 音频转录主函数
|
||
# ------------
|
||
@check_file_exists(_2_CLEANED_CHUNKS) # 检查清理后的音频片段文件是否存在的装饰器
|
||
def transcribe():
|
||
# ------------
|
||
# 步骤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) # 将视频文件转换为音频文件
|
||
|
||
# ------------
|
||
# 步骤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") # 标准化人声音频音量
|
||
else:
|
||
vocal_audio = _RAW_AUDIO_FILE # 如果未启用分离或模块不可用,直接使用原始音频文件
|
||
|
||
# ------------
|
||
# 步骤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格式结果
|
||
|
||
# ------------
|
||
# 新增函数:保存标准化的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]")
|
||
|
||
if __name__ == "__main__": # 主程序入口
|
||
transcribe() # 执行转录函数 |