Skip to content

extract_trim_video_audio

ExtractTrimVideoAudio

Bases: Extractor

Trim with ffmpeg "mov" and "wav" files.

Source code in client/ayon_traypublisher/plugins/publish/extract_trim_video_audio.py
 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)}")