236 lines
7.6 KiB
Python
236 lines
7.6 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
"""
|
|||
|
|
VideoLingo 非图形界面版本
|
|||
|
|
支持通过参数赋值的方式处理视频
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import os
|
|||
|
|
import sys
|
|||
|
|
import shutil
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
# 设置路径
|
|||
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|||
|
|
os.environ['PATH'] += os.pathsep + current_dir
|
|||
|
|
sys.path.append(current_dir)
|
|||
|
|
|
|||
|
|
# 导入核心模块
|
|||
|
|
from core.utils.config_utils import load_key, update_key
|
|||
|
|
from core.utils.onekeycleanup import cleanup
|
|||
|
|
from core.utils.delete_retry_dubbing import delete_dubbing_files
|
|||
|
|
from translations.translations import translate as t
|
|||
|
|
from core import (
|
|||
|
|
_2_asr, _3_1_split_nlp, _3_2_split_meaning,
|
|||
|
|
_4_1_summarize, _4_2_translate, _5_split_sub,
|
|||
|
|
_6_gen_sub, _7_sub_into_vid, _8_1_audio_task,
|
|||
|
|
_8_2_dub_chunks, _9_refer_audio, _10_gen_audio,
|
|||
|
|
_11_merge_audio, _12_dub_to_vid
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class VideoLingoProcessor:
|
|||
|
|
"""VideoLingo 视频处理器"""
|
|||
|
|
|
|||
|
|
def __init__(self, input_path, output_dir="output"):
|
|||
|
|
"""
|
|||
|
|
初始化处理器
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
input_path (str): 输入视频文件路径
|
|||
|
|
output_dir (str): 输出目录路径,默认为 "output"
|
|||
|
|
"""
|
|||
|
|
self.input_path = Path(input_path)
|
|||
|
|
self.output_dir = Path(output_dir)
|
|||
|
|
|
|||
|
|
# 验证输入文件
|
|||
|
|
if not self.input_path.exists():
|
|||
|
|
raise FileNotFoundError(f"输入文件不存在: {self.input_path}")
|
|||
|
|
|
|||
|
|
# 创建输出目录
|
|||
|
|
self.output_dir.mkdir(exist_ok=True)
|
|||
|
|
|
|||
|
|
# 设置输出文件路径
|
|||
|
|
self.sub_video = self.output_dir / "output_sub.mp4"
|
|||
|
|
self.dub_video = self.output_dir / "output_dub.mp4"
|
|||
|
|
|
|||
|
|
print(f"📹 输入视频: {self.input_path}")
|
|||
|
|
print(f"📁 输出目录: {self.output_dir}")
|
|||
|
|
|
|||
|
|
def setup_video_file(self):
|
|||
|
|
"""设置视频文件到指定位置"""
|
|||
|
|
# 将输入视频复制到 "output" 目录
|
|||
|
|
output_dir = Path("output")
|
|||
|
|
output_dir.mkdir(exist_ok=True)
|
|||
|
|
|
|||
|
|
target_video = output_dir / self.input_path.name
|
|||
|
|
if not target_video.exists():
|
|||
|
|
print(f"📋 复制视频文件到: {target_video}")
|
|||
|
|
shutil.copy2(self.input_path, target_video)
|
|||
|
|
|
|||
|
|
return target_video
|
|||
|
|
|
|||
|
|
def process_subtitles(self):
|
|||
|
|
"""处理字幕生成"""
|
|||
|
|
print("\n🎬 开始字幕处理流程...")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
print("🎤 使用 Whisper 进行语音转录...")
|
|||
|
|
_2_asr.transcribe()
|
|||
|
|
|
|||
|
|
print("✂️ 拆分长句子...")
|
|||
|
|
_3_1_split_nlp.split_by_spacy()
|
|||
|
|
_3_2_split_meaning.split_sentences_by_meaning()
|
|||
|
|
|
|||
|
|
print("📝 总结和翻译...")
|
|||
|
|
_4_1_summarize.get_summary()
|
|||
|
|
|
|||
|
|
# 检查是否需要暂停编辑术语
|
|||
|
|
if load_key("pause_before_translate"):
|
|||
|
|
input("⚠️ 暂停以便编辑术语。请前往 'output/log/terminology.json' 编辑术语表,然后按回车继续...")
|
|||
|
|
|
|||
|
|
_4_2_translate.translate_all()
|
|||
|
|
|
|||
|
|
print("⏱️ 处理和对齐字幕...")
|
|||
|
|
_5_split_sub.split_for_sub_main()
|
|||
|
|
_6_gen_sub.align_timestamp_main()
|
|||
|
|
|
|||
|
|
print("🎞️ 将字幕合并到视频...")
|
|||
|
|
_7_sub_into_vid.merge_subtitles_to_video()
|
|||
|
|
|
|||
|
|
print("✅ 字幕处理完成! 🎉")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"❌ 字幕处理失败: {str(e)}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def process_dubbing(self):
|
|||
|
|
"""处理配音生成"""
|
|||
|
|
print("\n🎙️ 开始配音处理流程...")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
print("📋 生成音频任务...")
|
|||
|
|
_8_1_audio_task.gen_audio_task_main()
|
|||
|
|
_8_2_dub_chunks.gen_dub_chunks()
|
|||
|
|
|
|||
|
|
print("🎵 提取参考音频...")
|
|||
|
|
_9_refer_audio.extract_refer_audio_main()
|
|||
|
|
|
|||
|
|
print("🔊 生成所有音频...")
|
|||
|
|
_10_gen_audio.gen_audio()
|
|||
|
|
|
|||
|
|
print("🎶 合并完整音频...")
|
|||
|
|
_11_merge_audio.merge_full_audio()
|
|||
|
|
|
|||
|
|
print("🎬 将配音合并到视频...")
|
|||
|
|
_12_dub_to_vid.merge_video_audio()
|
|||
|
|
|
|||
|
|
print("✅ 配音处理完成! 🎇")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"❌ 配音处理失败: {str(e)}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def process_all(self, include_dubbing=True):
|
|||
|
|
"""
|
|||
|
|
执行完整的处理流程
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
include_dubbing (bool): 是否包含配音处理,默认为 True
|
|||
|
|
"""
|
|||
|
|
print("🚀 开始 VideoLingo 处理流程")
|
|||
|
|
print("=" * 50)
|
|||
|
|
|
|||
|
|
# 设置视频文件
|
|||
|
|
self.setup_video_file()
|
|||
|
|
|
|||
|
|
# 处理字幕
|
|||
|
|
subtitle_success = self.process_subtitles()
|
|||
|
|
if not subtitle_success:
|
|||
|
|
print("❌ 字幕处理失败,停止执行")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
# 如果字幕成功且需要配音,则处理配音
|
|||
|
|
if include_dubbing:
|
|||
|
|
dubbing_success = self.process_dubbing()
|
|||
|
|
if not dubbing_success:
|
|||
|
|
print("❌ 配音处理失败")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
print("\n🎊 所有处理完成!")
|
|||
|
|
print(f"📁 输出文件位于: {self.output_dir.absolute()}")
|
|||
|
|
|
|||
|
|
# 显示输出文件
|
|||
|
|
if self.sub_video.exists():
|
|||
|
|
print(f" 🎬 字幕视频: {self.sub_video}")
|
|||
|
|
if include_dubbing and self.dub_video.exists():
|
|||
|
|
print(f" 🎙️ 配音视频: {self.dub_video}")
|
|||
|
|
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
def cleanup_files(self):
|
|||
|
|
"""清理临时文件"""
|
|||
|
|
print("🧹 清理临时文件...")
|
|||
|
|
cleanup()
|
|||
|
|
print("✅ 清理完成")
|
|||
|
|
|
|||
|
|
def delete_dubbing_files(self):
|
|||
|
|
"""删除配音相关文件"""
|
|||
|
|
print("🗑️ 删除配音文件...")
|
|||
|
|
delete_dubbing_files()
|
|||
|
|
print("✅ 配音文件删除完成")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def main():
|
|||
|
|
"""主函数 - 示例用法"""
|
|||
|
|
|
|||
|
|
# ==================== 配置参数 ====================
|
|||
|
|
# 请在这里修改您的参数
|
|||
|
|
|
|||
|
|
# 输入视频路径(必需)
|
|||
|
|
INPUT_VIDEO_PATH = "/root/autodl-tmp/output/Dajing_Gate/video_gen_20250721_145356/videos/composed_video_20250721_145724.mp4"
|
|||
|
|
|
|||
|
|
# 输出目录(可选,默认为 "output")
|
|||
|
|
OUTPUT_DIR = "output"
|
|||
|
|
|
|||
|
|
# 处理选项
|
|||
|
|
INCLUDE_DUBBING = True # 是否包含配音处理
|
|||
|
|
|
|||
|
|
# ==================== 可选配置覆盖 ====================
|
|||
|
|
# 您可以在这里覆盖 config.yaml 中的设置
|
|||
|
|
|
|||
|
|
# 配置中文转英文翻译
|
|||
|
|
update_key("whisper.language", "zh") # 原始语言为中文
|
|||
|
|
update_key("target_language", "English") # 目标语言为英文
|
|||
|
|
update_key("tts_method", "edge_tts") # 使用 Edge TTS
|
|||
|
|
update_key("burn_subtitles", True) # 烧录字幕到视频
|
|||
|
|
|
|||
|
|
# ===================================================
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 创建处理器实例
|
|||
|
|
processor = VideoLingoProcessor(
|
|||
|
|
input_path=INPUT_VIDEO_PATH,
|
|||
|
|
output_dir=OUTPUT_DIR
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 执行处理
|
|||
|
|
success = processor.process_all(include_dubbing=INCLUDE_DUBBING)
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
print("\n🎉 处理成功完成!")
|
|||
|
|
else:
|
|||
|
|
print("\n❌ 处理过程中出现错误")
|
|||
|
|
|
|||
|
|
except FileNotFoundError as e:
|
|||
|
|
print(f"❌ 文件错误: {e}")
|
|||
|
|
print("请检查输入视频路径是否正确")
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"❌ 处理失败: {e}")
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
main()
|