LaiTool/resources/scripts/getgrame.py

170 lines
5.3 KiB
Python

# -*- 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-2023-12-07-git-f89cff96d0-full_build/bin/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}")