170 lines
5.3 KiB
Python
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}")
|