# -*- coding: utf-8 -*- import io import sys import public_tools import json import subprocess import os import shutil # sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') def init(draft_path, out_dir, package_path): class TimeObject: def __init__(self, **kwargs): self.__dict__.update(kwargs) # 剪映草稿目录 draft_folder = draft_path # 调用函数并获取选定的文件夹 json_path = os.path.join(draft_folder, "draft_content.json") with open(json_path, "r", encoding="utf-8") as file: json_data = json.load(file) if public_tools.check_if_folder_exists(out_dir, "tmp"): try: shutil.rmtree(os.path.join(out_dir, "tmp")) print("文件夹 tmp 删除成功。") except OSError as e: print(f"删除文件夹失败:{e}") try: os.mkdir(os.path.join(out_dir, "tmp")) os.mkdir(os.path.join(out_dir + "/tmp", "input_crop")) print("文件夹创建成功。") except OSError as e: print(f"创建文件夹失败:{e}") # 获取轨道 def find_node(nodes, type, val): for node in nodes: if node[type] == val: return node # 获取剪映的主轨道 video_nodes = find_node(json_data["tracks"], "type", "video")["segments"] # 先获取所有的场景的开始结束持续时间 # 获取分割数据 num = 1 time_list = [] for video_node in video_nodes: # 开始时间 start_time = video_node["target_timerange"]["start"] # 结束时间 end_time = ( video_node["target_timerange"]["start"] + video_node["target_timerange"]["duration"] ) # 持续时间 duration_time = end_time - start_time # 中间帧时间 middle_time = (end_time - start_time) / 2 middle_time = start_time + middle_time # 获取文件地址 video_id = video_node["material_id"] materials_node = find_node(json_data["materials"]["videos"], "id", video_id) video_path = materials_node["path"] time_list.append( TimeObject( start_time=start_time, end_time=end_time, duration_time=duration_time, middle_time=middle_time, video_path=video_path, ) ) num += 1 # 检查开始时间和结束时间是不是满足包含条件 def is_within_range(video_obj, text_start_time, text_end_time): return ( text_start_time >= video_obj.start_time and text_end_time <= video_obj.end_time ) # 处理文案 text_nodes = find_node(json_data["tracks"], "type", "text")["segments"] num = 0 text_value_list = [] temp_text_value = "" for text_node in text_nodes: text_start_time = text_node["target_timerange"]["start"] text_end_time = ( text_node["target_timerange"]["start"] + text_node["target_timerange"]["duration"] ) text_material_id = text_node["material_id"] text_content = find_node( json_data["materials"]["texts"], "id", text_material_id )["content"] text_content_json = json.loads(text_content) text_value = "".join(text_content_json["text"]) + "。" if is_within_range(time_list[num], text_start_time, text_end_time): temp_text_value += text_value else: text_value_list.append(temp_text_value) temp_text_value = text_value num += 1 text_value_list.append(temp_text_value) print("场景数:" + str(len(text_value_list))) # 写入txt文件 with open(os.path.join(out_dir, "文案.txt"), "w", encoding="utf-8") as file: for line in text_value_list: # 判断是不是最后一行,最后一行不需要换行 if text_value_list.index(line) == len(text_value_list) - 1: file.write(line) else: file.write(line + "\n") ffmpeg_path = os.path.join( package_path, "ffmpeg/win/ffmpeg" ) # 抽取关键帧 num = 1 for video_list in time_list: output_file = os.path.join( out_dir, "tmp/input_crop/" + str(num).zfill(5) + ".png" ) # FFmpeg命令 ffmpeg_command = [ ffmpeg_path, # 指定FFmpeg可执行文件的路径 "-ss", str( public_tools.convert_to_seconds(video_list.middle_time, 1) ), # 开始时间为1.2秒 "-i", video_list.video_path, # 输入文件 "-frames:v", "1", # 抽取1帧 output_file, # 输出文件 "-loglevel", "error", ] result = subprocess.run( ffmpeg_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # 检查返回代码 if result.returncode == 0: print("抽取成功,结果保存在", output_file) else: print("抽取失败,错误信息:", result.stderr.decode("utf-8")) num += 1 sys.stdout.flush() # 强制立即刷新输出缓冲区 print(f"抽取完成,结果保存在 {output_file}")