13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 | class ExtractTrimVideoAudio(publish.Extractor):
"""Trim with ffmpeg "mov" and "wav" files."""
# must be before `ExtractThumbnailSP`
order = pyblish.api.ExtractorOrder - 0.01
label = "Extract Trim Video/Audio"
hosts = ["traypublisher"]
families = ["clip", "trimming"]
# make sure it is enabled only if at least both families are available
match = pyblish.api.Subset
# presets
def process(self, instance):
representation = instance.data.get("representations")
self.log.debug(f"_ representation: {representation}")
if not representation:
instance.data["representations"] = list()
# get ffmpet path
ffmpeg_tool_args = get_ffmpeg_tool_args("ffmpeg")
# get staging dir
staging_dir = self.staging_dir(instance)
self.log.debug("Staging dir set to: `{}`".format(staging_dir))
# Generate mov file.
fps = instance.data["fps"]
video_file_path = instance.data["editorialSourcePath"]
extensions = instance.data.get("extensions", ["mov"])
output_file_type = instance.data.get("outputFileType")
reviewable = "review" in instance.data["families"]
frame_start = int(instance.data["frameStart"])
frame_end = int(instance.data["frameEnd"])
handle_start = instance.data["handleStart"]
handle_end = instance.data["handleEnd"]
clip_start_h = float(instance.data["clipInH"])
_dur = instance.data["clipDuration"]
handle_dur = (handle_start + handle_end)
clip_dur_h = float(_dur + handle_dur)
if output_file_type:
extensions = [output_file_type]
for ext in extensions:
self.log.debug("Processing ext: `{}`".format(ext))
if not ext.startswith("."):
ext = "." + ext
clip_trimed_path = os.path.join(
staging_dir, instance.data["name"] + ext)
if ext == ".wav":
# offset time as ffmpeg is having bug
clip_start_h += 0.5
# remove "review" from families
instance.data["families"] = [
fml for fml in instance.data["families"]
if "trimming" not in fml
]
ffmpeg_args = ffmpeg_tool_args + [
"-ss", str(clip_start_h / fps),
"-i", video_file_path,
"-t", str(clip_dur_h / fps)
]
if ext in [".mov", ".mp4"]:
ffmpeg_args.extend([
"-crf", "18",
"-pix_fmt", "yuv420p"
])
elif ext in ".wav":
ffmpeg_args.extend([
"-vn",
"-acodec", "pcm_s16le",
"-ar", "48000",
"-ac", "2"
])
# add output path
ffmpeg_args.append(clip_trimed_path)
joined_args = " ".join(ffmpeg_args)
self.log.debug(f"Processing: {joined_args}")
run_subprocess(
ffmpeg_args, logger=self.log
)
repre = {
"name": ext[1:],
"ext": ext[1:],
"files": os.path.basename(clip_trimed_path),
"stagingDir": staging_dir,
"frameStart": frame_start,
"frameEnd": frame_end,
"frameStartFtrack": frame_start - handle_start,
"frameEndFtrack": frame_end + handle_end,
"fps": fps,
"tags": []
}
if ext in [".mov", ".mp4"] and reviewable:
repre.update({
"thumbnail": True,
"tags": ["review", "ftrackreview", "delete"]})
instance.data["representations"].append(repre)
self.log.debug(f"Instance data: {pformat(instance.data)}")
|