mirror of
https://github.com/linyqh/NarratoAI.git
synced 2025-12-12 03:02:48 +00:00
运行成功,但脚本问题还很大
This commit is contained in:
parent
2bc94651a2
commit
a675e35f1d
@ -451,19 +451,19 @@ def gemini_video2json(video_origin_name: str, video_origin_path: str, video_plot
|
||||
""" % (language, video_plot)
|
||||
|
||||
logger.debug(f"视频名称: {video_origin_name}")
|
||||
try:
|
||||
gemini_video_file = gemini.upload_file(video_origin_path)
|
||||
logger.debug(f"上传视频至 Google cloud 成功: {gemini_video_file.name}")
|
||||
while gemini_video_file.state.name == "PROCESSING":
|
||||
import time
|
||||
time.sleep(1)
|
||||
gemini_video_file = gemini.get_file(gemini_video_file.name)
|
||||
logger.debug(f"视频当前状态(ACTIVE才可用): {gemini_video_file.state.name}")
|
||||
if gemini_video_file.state.name == "FAILED":
|
||||
raise ValueError(gemini_video_file.state.name)
|
||||
except Exception as err:
|
||||
logger.error(f"上传视频至 Google cloud 失败, 请检查 VPN 配置和 APIKey 是否正确 \n{traceback.format_exc()}")
|
||||
raise TimeoutError(f"上传视频至 Google cloud 失败, 请检查 VPN 配置和 APIKey 是否正确; {err}")
|
||||
# try:
|
||||
gemini_video_file = gemini.upload_file(video_origin_path)
|
||||
logger.debug(f"上传视频至 Google cloud 成功: {gemini_video_file.name}")
|
||||
while gemini_video_file.state.name == "PROCESSING":
|
||||
import time
|
||||
time.sleep(1)
|
||||
gemini_video_file = gemini.get_file(gemini_video_file.name)
|
||||
logger.debug(f"视频当前状态(ACTIVE才可用): {gemini_video_file.state.name}")
|
||||
if gemini_video_file.state.name == "FAILED":
|
||||
raise ValueError(gemini_video_file.state.name)
|
||||
# except Exception as err:
|
||||
# logger.error(f"上传视频至 Google cloud 失败, 请检查 VPN 配置和 APIKey 是否正确 \n{traceback.format_exc()}")
|
||||
# raise TimeoutError(f"上传视频至 Google cloud 失败, 请检查 VPN 配置和 APIKey 是否正确; {err}")
|
||||
|
||||
streams = model.generate_content([prompt, gemini_video_file], stream=True)
|
||||
response = []
|
||||
@ -490,7 +490,7 @@ if __name__ == "__main__":
|
||||
# sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
#
|
||||
video_subject = "卖菜大妈竟是皇嫂"
|
||||
video_path = "/NarratoAI/resource/videos/demoyasuo.mp4"
|
||||
video_path = "../../resource/videos/demoyasuo.mp4"
|
||||
|
||||
video_plot = ''' '''
|
||||
language = "zh-CN"
|
||||
|
||||
@ -440,12 +440,13 @@ def start_subclip(task_id, params: VideoClipParams, subclip_path_videos):
|
||||
|
||||
logger.info(f"\n\n## 6. 最后一步: {index} => {final_video_path}")
|
||||
# 把所有东西合到在一起
|
||||
video.generate_video(video_path=combined_video_path,
|
||||
audio_path=audio_file,
|
||||
subtitle_path=subtitle_path,
|
||||
output_file=final_video_path,
|
||||
params=params,
|
||||
)
|
||||
video.generate_video_v2(
|
||||
video_path=combined_video_path,
|
||||
audio_paths=audio_files,
|
||||
subtitle_path=subtitle_path,
|
||||
output_file=final_video_path,
|
||||
params=params,
|
||||
)
|
||||
|
||||
_progress += 50 / params.video_count / 2
|
||||
sm.state.update_task(task_id, progress=_progress)
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import re
|
||||
import os
|
||||
import glob
|
||||
import random
|
||||
from typing import List
|
||||
@ -369,10 +370,17 @@ def generate_video_v2(
|
||||
return _clip
|
||||
|
||||
video_clip = VideoFileClip(video_path)
|
||||
original_audio = video_clip.audio # 保存原始视频的音轨
|
||||
video_duration = video_clip.duration
|
||||
|
||||
# 处理多个音频文件
|
||||
audio_clips = []
|
||||
for audio_path in audio_paths:
|
||||
# 确保每个音频文件路径是正确的
|
||||
if not os.path.exists(audio_path):
|
||||
logger.warning(f"音频文件不存在: {audio_path}")
|
||||
continue
|
||||
|
||||
# 从文件名中提取时间信息
|
||||
match = re.search(r'audio_(\d{2}-\d{2}-\d{2}-\d{2})\.mp3', os.path.basename(audio_path))
|
||||
if match:
|
||||
@ -382,28 +390,53 @@ def generate_video_v2(
|
||||
end_time = sum(int(x) * 60 ** i for i, x in enumerate(reversed(end)))
|
||||
|
||||
audio_clip = AudioFileClip(audio_path).volumex(params.voice_volume)
|
||||
audio_clip = audio_clip.set_start(start_time).set_end(end_time)
|
||||
|
||||
# 确保结束时间不超过音频实际长度
|
||||
actual_end_time = min(end_time - start_time, audio_clip.duration)
|
||||
|
||||
audio_clip = audio_clip.subclip(0, actual_end_time)
|
||||
audio_clip = audio_clip.set_start(start_time).set_end(start_time + actual_end_time)
|
||||
audio_clips.append(audio_clip)
|
||||
else:
|
||||
logger.warning(f"无法从文件名解析时间信息: {audio_path}")
|
||||
|
||||
# 合并所有音频剪辑
|
||||
# 合并所有音频剪辑,包括原始音轨
|
||||
if audio_clips:
|
||||
audio_clips.insert(0, original_audio) # 将原始音轨添加到音频剪辑列表的开头
|
||||
audio_clip = CompositeAudioClip(audio_clips)
|
||||
else:
|
||||
logger.warning("没有有效的音频文件")
|
||||
audio_clip = AudioClip(lambda t: 0, duration=video_clip.duration)
|
||||
logger.warning("没有有效的音频文件,使用原始音轨")
|
||||
audio_clip = original_audio
|
||||
|
||||
# 字幕处理部分保持不变
|
||||
# 字幕处理部分
|
||||
if subtitle_path and os.path.exists(subtitle_path):
|
||||
sub = SubtitlesClip(subtitles=subtitle_path, encoding="utf-8")
|
||||
text_clips = []
|
||||
|
||||
for item in sub.subtitles:
|
||||
clip = create_text_clip(subtitle_item=item)
|
||||
|
||||
# 确保字幕的开始时间不早于视频开始
|
||||
start_time = max(clip.start, 0)
|
||||
|
||||
# 如果字幕的开始时间晚于视频结束时间,则跳过此字幕
|
||||
if start_time >= video_duration:
|
||||
continue
|
||||
|
||||
# 调整字幕的结束时间,但不要超过视频长度
|
||||
end_time = min(clip.end, video_duration)
|
||||
|
||||
# 调整字幕的时间范围
|
||||
clip = clip.set_start(start_time).set_end(end_time)
|
||||
|
||||
text_clips.append(clip)
|
||||
|
||||
logger.info(f"处理了 {len(text_clips)} 段字幕")
|
||||
|
||||
# 创建一个新的视频剪辑,包含所有字幕
|
||||
video_clip = CompositeVideoClip([video_clip, *text_clips])
|
||||
|
||||
# 背景音乐处理部分保持不变
|
||||
# 背景音乐处理部分
|
||||
bgm_file = get_bgm_file(bgm_type=params.bgm_type, bgm_file=params.bgm_file)
|
||||
if bgm_file:
|
||||
try:
|
||||
@ -573,39 +606,43 @@ def combine_clip_videos(combined_video_path: str,
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
combined_video_path = "../../storage/tasks/12312312/com123.mp4"
|
||||
|
||||
video_paths = ['../../storage/cache_videos/vid-00_00-00_03.mp4',
|
||||
'../../storage/cache_videos/vid-00_03-00_07.mp4',
|
||||
'../../storage/cache_videos/vid-00_12-00_17.mp4',
|
||||
'../../storage/cache_videos/vid-00_26-00_31.mp4']
|
||||
video_ost_list = [False, True, False, True]
|
||||
list_script = [
|
||||
{
|
||||
"picture": "夜晚,一个小孩在树林里奔跑,后面有人拿着火把在追赶",
|
||||
"timestamp": "00:00-00:03",
|
||||
"narration": "夜黑风高的树林,一个小孩在拼命奔跑,后面的人穷追不舍!",
|
||||
"OST": False
|
||||
},
|
||||
{
|
||||
"picture": "追赶的人命令抓住小孩",
|
||||
"timestamp": "00:03-00:07",
|
||||
"narration": "原声播放1",
|
||||
"OST": True
|
||||
},
|
||||
{
|
||||
"picture": "小孩躲在草丛里,黑衣人用脚踢了踢他",
|
||||
"timestamp": "00:12-00:17",
|
||||
"narration": "小孩脱下外套,跑进树林, 一路奔跑,直到第二天清晨",
|
||||
"OST": False
|
||||
},
|
||||
{
|
||||
"picture": "小孩跑到车前,慌慌张张地对女人说有人要杀他",
|
||||
"timestamp": "00:26-00:31",
|
||||
"narration": "原声播放2",
|
||||
"OST": True
|
||||
}
|
||||
]
|
||||
# combined_video_path = "../../storage/tasks/12312312/com123.mp4"
|
||||
#
|
||||
# video_paths = ['../../storage/cache_videos/vid-00_00-00_03.mp4',
|
||||
# '../../storage/cache_videos/vid-00_03-00_07.mp4',
|
||||
# '../../storage/cache_videos/vid-00_12-00_17.mp4',
|
||||
# '../../storage/cache_videos/vid-00_26-00_31.mp4']
|
||||
# video_ost_list = [False, True, False, True]
|
||||
# list_script = [
|
||||
# {
|
||||
# "picture": "夜晚,一个小孩在树林里奔跑,后面有人拿着火把在追赶",
|
||||
# "timestamp": "00:00-00:03",
|
||||
# "narration": "夜黑风高的树林,一个小孩在拼命奔跑,后面的人穷追不舍!",
|
||||
# "OST": False,
|
||||
# "new_timestamp": "00:00-00:03"
|
||||
# },
|
||||
# {
|
||||
# "picture": "追赶的人命令抓住小孩",
|
||||
# "timestamp": "00:03-00:07",
|
||||
# "narration": "原声播放1",
|
||||
# "OST": True,
|
||||
# "new_timestamp": "00:03-00:07"
|
||||
# },
|
||||
# {
|
||||
# "picture": "小孩躲在草丛里,黑衣人用脚踢了踢他",
|
||||
# "timestamp": "00:12-00:17",
|
||||
# "narration": "小孩脱下外套,跑进树林, 一路奔跑,直到第二天清晨",
|
||||
# "OST": False,
|
||||
# "new_timestamp": "00:07-00:12"
|
||||
# },
|
||||
# {
|
||||
# "picture": "小孩跑到车前,慌慌张张地对女人说有人要杀他",
|
||||
# "timestamp": "00:26-00:31",
|
||||
# "narration": "原声播放2",
|
||||
# "OST": True,
|
||||
# "new_timestamp": "00:12-00:17"
|
||||
# }
|
||||
# ]
|
||||
# combine_clip_videos(combined_video_path=combined_video_path, video_paths=video_paths, video_ost_list=video_ost_list, list_script=list_script)
|
||||
|
||||
cfg = VideoClipParams()
|
||||
@ -633,14 +670,18 @@ if __name__ == "__main__":
|
||||
# params=cfg
|
||||
# )
|
||||
|
||||
video_path = "../../storage/tasks/12312312/com123.mp4"
|
||||
video_path = "../../storage/tasks/7f5ae494-abce-43cf-8f4f-4be43320eafa/combined-1.mp4"
|
||||
|
||||
audio_paths = ['../../storage/tasks/12312312/audio_00-00-00-03.mp3',
|
||||
'../../storage/tasks/12312312/audio_00-12-00-17.mp3']
|
||||
audio_paths = ['../../storage/tasks/7f5ae494-abce-43cf-8f4f-4be43320eafa/audio_00-00-00-07.mp3',
|
||||
'../../storage/tasks/7f5ae494-abce-43cf-8f4f-4be43320eafa/audio_00-14-00-17.mp3',
|
||||
'../../storage/tasks/7f5ae494-abce-43cf-8f4f-4be43320eafa/audio_00-17-00-22.mp3',
|
||||
'../../storage/tasks/7f5ae494-abce-43cf-8f4f-4be43320eafa/audio_00-34-00-45.mp3',
|
||||
'../../storage/tasks/7f5ae494-abce-43cf-8f4f-4be43320eafa/audio_00-59-01-09.mp3',
|
||||
]
|
||||
|
||||
subtitle_path = "../../storage/tasks/12312312/subtitle_multiple.srt"
|
||||
subtitle_path = "../../storage/tasks/7f5ae494-abce-43cf-8f4f-4be43320eafa\subtitle.srt"
|
||||
|
||||
output_file = "../../storage/tasks/12312312/out123.mp4"
|
||||
output_file = "../../storage/tasks/7f5ae494-abce-43cf-8f4f-4be43320eafa/final-123.mp4"
|
||||
|
||||
generate_video_v2(video_path=video_path,
|
||||
audio_paths=audio_paths,
|
||||
|
||||
@ -1213,7 +1213,7 @@ def create_subtitle_from_multiple(text: str, sub_maker_list: List[SubMaker], lis
|
||||
if script_item['OST']:
|
||||
continue
|
||||
|
||||
start_time, end_time = script_item['timestamp'].split('-')
|
||||
start_time, end_time = script_item['new_timestamp'].split('-')
|
||||
if sub_maker_index >= len(sub_maker_list):
|
||||
logger.error(f"Sub maker list index out of range: {sub_maker_index}")
|
||||
break
|
||||
@ -1317,7 +1317,7 @@ def tts_multiple(task_id: str, list_script: list, voice_name: str, voice_rate: f
|
||||
|
||||
for item in list_script:
|
||||
if not item['OST']:
|
||||
timestamp = item['timestamp'].replace(':', '-')
|
||||
timestamp = item['new_timestamp'].replace(':', '-')
|
||||
audio_file = os.path.join(output_dir, f"audio_{timestamp}.mp3")
|
||||
|
||||
# 检查文件是否已存在,如存在且不强制重新生成,则跳过
|
||||
|
||||
@ -7,7 +7,7 @@ from loguru import logger
|
||||
import json
|
||||
from uuid import uuid4
|
||||
import urllib3
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from app.models import const
|
||||
|
||||
@ -326,3 +326,42 @@ def calculate_total_duration(scenes):
|
||||
total_seconds += duration.total_seconds()
|
||||
|
||||
return total_seconds
|
||||
|
||||
|
||||
def add_new_timestamps(scenes):
|
||||
"""
|
||||
新增新视频的时间戳,并为"原生播放"的narration添加唯一标识符
|
||||
Args:
|
||||
scenes: 场景列表
|
||||
|
||||
Returns:
|
||||
更新后的场景列表
|
||||
"""
|
||||
current_time = timedelta()
|
||||
updated_scenes = []
|
||||
|
||||
for scene in scenes:
|
||||
new_scene = scene.copy() # 创建场景的副本,以保留原始数据
|
||||
start, end = new_scene['timestamp'].split('-')
|
||||
start_time = datetime.strptime(start, '%M:%S')
|
||||
end_time = datetime.strptime(end, '%M:%S')
|
||||
duration = end_time - start_time
|
||||
|
||||
new_start = current_time
|
||||
current_time += duration
|
||||
new_end = current_time
|
||||
|
||||
# 将 timedelta 转换为分钟和秒
|
||||
new_start_str = f"{int(new_start.total_seconds() // 60):02d}:{int(new_start.total_seconds() % 60):02d}"
|
||||
new_end_str = f"{int(new_end.total_seconds() // 60):02d}:{int(new_end.total_seconds() % 60):02d}"
|
||||
|
||||
new_scene['new_timestamp'] = f"{new_start_str}-{new_end_str}"
|
||||
|
||||
# 为"原生播放"的narration添加唯一标识符
|
||||
if new_scene.get('narration') == "原声播放":
|
||||
unique_id = str(uuid4())[:8] # 使用UUID的前8个字符作为唯一标识符
|
||||
new_scene['narration'] = f"原声播放_{unique_id}"
|
||||
|
||||
updated_scenes.append(new_scene)
|
||||
|
||||
return updated_scenes
|
||||
|
||||
@ -395,7 +395,7 @@ with left_panel:
|
||||
# 去掉json的头尾标识
|
||||
input_json = input_json.strip('```json').strip('```')
|
||||
try:
|
||||
data = json.loads(input_json)
|
||||
data = utils.add_new_timestamps(json.loads(input_json))
|
||||
except Exception as err:
|
||||
raise ValueError(
|
||||
f"视频脚本格式错误,请检查脚本是否符合 JSON 格式;{err} \n\n{traceback.format_exc()}")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user