Beispiel #1
0
def ffmpeg_subtitles_filter(stream, subtitle_path, start_ms):
    font_dir = current_app.config.get('FF_FONT_DIR', None)
    font_name = current_app.config.get('FF_FONT_NAME', None)
    font_size = current_app.config.get('FF_FONT_SIZE', 24)

    stream = ffmpeg.setpts(stream, 'PTS+%f/TB' % (start_ms / 1000))
    sargs = {'force_style': 'Fontsize=%d' % font_size}
    if font_dir is not None:
        sargs['fontsdir'] = str(font_dir)
    if font_name is not None:
        sargs['force_style'] += ',FontName=%s' % font_name
    stream = ffmpeg.filter_(stream, 'subtitles', str(subtitle_path), **sargs)
    stream = ffmpeg.setpts(stream, 'PTS-STARTPTS')
    return stream
def speed_up(video_download, speed=args.speed):
    """Speeds up a video using ffmpeg. Works as a youtube_dl progress hook.

    The original video will be deleted. The speed multiplier is the 'speed' constant.

    Args:
        video_download -- dict with a 'status' key and a 'filename' key.
    """
    if not video_download['status'] == 'finished':
        return
    # filename, file_extension = os.path.splitext(video_download['filename'])
    # filename_no_extension = video_download['filename'][:-len(file_extension)]
    filename = Path(video_download['filename'])
    out_name = filename.with_stem(
        filename.stem.replace("'", '') + f'-{speed}x').name
    speedup_folder = filename.parents[1] / 'speedup'
    speedup_folder.mkdir(exist_ok=True)
    out_filename = speedup_folder / out_name

    stream = ffmpeg.input(str(filename))
    stream = ffmpeg.setpts(stream, f'(1/{speed})*PTS')
    stream = ffmpeg.output(stream, str(out_filename))
    # if not args.verbose:
    #     stream = stream.global_args('-hide_banner')
    #     # stream = stream.global_args('-loglevel', 'warning')
    ffmpeg.run(stream)

    if not args.keep_original_parts:
        filename.unlink()
Beispiel #3
0
def cut(video, audio, arg):
    st, end = arg
    video = ffmpeg.trim(video, start=st, end=end)
    video = ffmpeg.setpts(video, 'PTS-STARTPTS')
    audio = ffmpeg.filter(audio, 'atrim', start=st, end=end)
    audio = ffmpeg.filter(audio, 'asetpts', 'PTS-STARTPTS')
    return video, audio
Beispiel #4
0
 def _estublish_cmd(self, scenes: List[Scene]):
     inputfile = self.input_media_path.as_posix()
     outputfile = self.output_media_path.as_posix()
     stream = ffmpeg.input(inputfile)
     video_streams = list()
     audio_streams = list()
     for scene in scenes:
         start = scene.get_startat()
         duration = scene.get_interval()
         v_clip_stream = ffmpeg.trim(
             stream, start=start, duration=duration)
         v_clip_stream = ffmpeg.setpts(v_clip_stream, 'PTS-STARTPTS')
         a_clip_stream = ffmpeg.filter_(
             stream, 'atrim', start=start, duration=duration)
         a_clip_stream = ffmpeg.filter_(
             a_clip_stream, 'asetpts', 'PTS-STARTPTS')
         video_streams.append(v_clip_stream)
         audio_streams.append(a_clip_stream)
     v_stream = ffmpeg.concat(
         *video_streams, n=len(video_streams), v=1, a=0)
     a_stream = ffmpeg.concat(
         *audio_streams, n=len(audio_streams), v=0, a=1)
     stream = ffmpeg.output(
         v_stream, a_stream, outputfile, **self.CONFIG_720P)
     # ffmpeg.view(stream)  # Debug
     self.stream = stream
     return ' '.join(ffmpeg.compile(stream))
Beispiel #5
0
def process(inputfile, day):
    duration = videoInf(inputfile)
    #find and sets presentation timestamps for 1min video
    pts = str(1 / duration) + "*PTS"
    stream = ffmpeg.input(inputfile)
    stream = ffmpeg.setpts(stream, pts)
    #merge the stream with music track
    audio = ffmpeg.input('../audio/track1.mp3')
    stream = ffmpeg.output(audio, stream, day + 'twim.mp4')
    ffmpeg.run(stream)
Beispiel #6
0
def speed(video, audio, arg):
    video = ffmpeg.setpts(video, '{}*PTS'.format(arg))
    if arg < 0.5:
        video = ffmpeg.filter(video,
                              'minterpolate',
                              mi_mode='mci',
                              mc_mode='aobmc',
                              vsbmc=1,
                              fps=120)
    audio = ffmpeg.filter(audio, 'asetpts', '{}*PTS'.format(arg))
    return video, audio
Beispiel #7
0
    def run(self, item: VideoItem):
        print("Start exporting file")
        metadata = iExecutor.get_metadata(item)
        video = VideoFile(item.filepath)
        video.set_index(metadata.start_i)
        video_width = video.get_frame_width()
        video_height = video.get_frame_height()
        timeframes = video.get_timeframe_range(metadata.end_i)
        timeframes = np.array(timeframes)
        bbs = metadata.bb_fields.get_bbs_as_arrs()
        if bbs is None or len(bbs) == 0:
            raise SkipSignal("No bounding box fields for this item")
        collision_locations = metadata.bb_fields.collision_locations

        if not metadata.start_i:
            raise SkipSignal(f"Metadata is not clipped")
        if not metadata.end_i:
            raise SkipSignal(f"Metadata is not clipped")
        begin = metadata.start_i
        end = metadata.end_i
        time_begin = timeframes[0]
        time_end = timeframes[-1]
        headers = [FRAME, ID, CLASS, X1, Y1, X2, Y2, HAS_COLLISION]

        dtype = [
            (FRAME, np.int),
            (ID, np.int),
            (CLASS, np.object),
            (X1, np.float),
            (Y1, np.float),
            (X2, np.float),
            (Y2, np.float),
            (HAS_COLLISION, np.int),
        ]

        data = np.array(bbs, dtype=dtype)

        #data = np.array([*zip(frames, bbs[ID], bbs[CLASS], 
        #    bbs[X1], bbs[Y1], bbs[X2], bbs[Y2], bbs[HAS_COLLISION])])

        # Sort data by object id
        data = np.sort(data, order=ID)

        # Group data by object id
        _, unique_indices = np.unique(data[ID], return_index=True)
        data = np.split(data, unique_indices[1:], axis=0)

        interp_data = []
        n_frames = int((time_end - time_begin) * self.target_fps / 1000) 
        interp_time = time_begin + np.arange(n_frames) * (time_end - time_begin) / (n_frames - 1)
        for unique_object in data:
            if unique_object.shape[0] == 0:
                continue
            # Sort data by frame
            unique_object = np.sort(unique_object, order=FRAME)
            # Deal with holes
            interp_frame = np.arange(n_frames)
            holes, = np.where((unique_object[FRAME][1:] - unique_object[FRAME][:-1]) != 1)
            # Need +1 to have correct index for insertion
            holes = holes + 1
            label_id = unique_object[ID][0]
            label_class = unique_object[CLASS][0]
            label_collision = unique_object[HAS_COLLISION][0]
            nan_frame = (0, label_id, label_class, np.nan, np.nan, np.nan, np.nan, label_collision)
            time = timeframes[unique_object[FRAME]]
            unique_object = np.insert(unique_object, holes, nan_frame, axis=0)
            time = np.insert(time, holes, np.nan)
            interp_x1 = np.interp(interp_time, time, unique_object['x1s'], left=float('nan'), right=float('nan'))
            interp_x1 = interp_x1.clip(0, video_width - 1)
            interp_y1 = np.interp(interp_time, time, unique_object['y1s'], left=float('nan'), right=float('nan'))
            interp_y1 = interp_y1.clip(0, video_height - 1)
            interp_x2 = np.interp(interp_time, time, unique_object['x2s'], left=float('nan'), right=float('nan'))
            interp_x2 = interp_x2.clip(0, video_width - 1)
            interp_y2 = np.interp(interp_time, time, unique_object['y2s'], left=float('nan'), right=float('nan'))
            interp_y2 = interp_y2.clip(0, video_height - 1)
            interp_data += [ (frame, label_id, label_class, x1, y1, x2, y2, label_collision) 
                    for (frame, x1, y1, x2, y2) 
                    in zip(interp_frame, interp_x1, interp_y1,
                        interp_x2, interp_y2)
                    ]

        
        # Sort data by frame
        interp_data = np.array(interp_data, dtype=dtype)
        nan_mask = np.array([list(row) for row in interp_data[['x1s','x2s','y1s','y2s']]])
        nan_mask = np.any(np.isnan(nan_mask), axis=1)
        interp_data = interp_data[~nan_mask]
        interp_data = interp_data[np.argsort(interp_data['frames']), ...]
        interp_data['x1s'] = np.round(interp_data['x1s'])
        interp_data['y1s'] = np.round(interp_data['y1s'])
        interp_data['x2s'] = np.round(interp_data['x2s'])
        interp_data['y2s'] = np.round(interp_data['y2s'])

        directory = STORAGE_DIR_POSITIVES if len(collision_locations) else STORAGE_DIR_NEGATIVES
        filename = str(metadata.id) + ".csv"
        np.savetxt(directory / filename, interp_data, delimiter=',',
            fmt='%d,%d,%s,%d,%d,%d,%d,%d',
            comments='')
        stream = ffmpeg.input(item.filepath)
        stream = stream.trim(start_frame=begin, end_frame=end, duration=5)
        stream = ffmpeg.filter(stream, 'fps', fps=self.target_fps, round='near')
        stream = ffmpeg.setpts(stream, expr='PTS-STARTPTS')
        stream = stream.output(str(STORAGE_DIR_VIDEOS / (str(metadata.id) + '.mp4')))
        stream = ffmpeg.overwrite_output(stream)
        try:
            stream.run()
        except KeyboardInterrupt:
            # Prevent corrupting video
            stream.run()
            raise
        print(f"Done exporting file {filename}")
        return item
Beispiel #8
0
    def run(self, item: VideoItem):
        print("Start exporting file")
        metadata = iExecutor.get_metadata(item)
        bbs = metadata.bb_fields.to_json()
        if bbs is None or len(bbs) == 0:
            raise StopSignal("No bounding box fields for this item")

        # First, we trim the last seconds before the first collision
        if not metadata.accident_locations or len(
                metadata.accident_locations) == 0:
            # TODO: This should be a negative
            raise StopSignal(f"No accident locations labelled for {item.id}")
        if not metadata.start_i:
            raise StopSignal(f"Metadata is not clipped")
        collision_frame = np.min(metadata.accident_locations)
        info = ffmpeg.probe(item.filepath)
        streams = [
            stream for stream in info.get('streams', [])
            if stream.get('codec_type') == 'video'
        ]
        if len(streams) > 1:
            raise StopSignal(
                f"Video {item.id} has multiple video streams. Could not determine FPS"
            )
        if len(streams) < 1:
            raise StopSignal(
                f"Video {item.id} has no video streams. Could not determine FPS"
            )
        fps = float(streams[0]['nb_frames']) / float(streams[0]['duration'])

        headers = [FRAME, ID, CLASS, X1, Y1, X2, Y2, HAS_COLLISION]

        #dtype = [
        #    (FRAME, np.uint),
        #    (ID, np.uint),
        #    (CLASS, np.object),
        #    (X1, np.uint),
        #    (Y1, np.uint),
        #    (X2, np.uint),
        #    (Y2, np.uint),
        #    (HAS_COLLISION, np.uint),
        #]

        begin = int(collision_frame - np.floor(self.clip_len_s * fps))
        if begin + self.len_thresh_s * fps < 0:
            # We are under the minimum threshold
            raise StopSignal(
                f"Video {item.id} is shorter than {self.len_thresh_s}s")
        begin = max(begin, 0)

        normalized_frames = np.array(bbs[FRAME]).astype(np.int) - begin

        data = np.array([
            *zip(normalized_frames, bbs[ID], bbs[CLASS], bbs[X1], bbs[Y1],
                 bbs[X2], bbs[Y2], bbs[HAS_COLLISION])
        ],
                        dtype=str)

        data = data[np.logical_and(
            normalized_frames >= 0, normalized_frames <= collision_frame -
            begin), ...]

        # Sort data by frame
        data = data[np.argsort(data[:, 0].astype(int)), ...]

        # Group data by frame
        _, unique_indices = np.unique(data[:, 0].astype(np.int),
                                      return_index=True)
        data = np.array(np.split(data, unique_indices[1:], axis=0))

        # Mask for downsampling fps
        n_input_frames = collision_frame - begin
        n_output_frames = round(n_input_frames * (self.target_fps / fps))
        sample_interval = float(n_input_frames) / n_output_frames

        # select frames to sample
        mask = np.round(np.arange(n_output_frames) *
                        sample_interval).astype(int)
        mask = np.minimum(mask, data.shape[0] - 1)

        # Duplicate frames
        # n_duplicate = n_input_frames - n_output_frames
        # dup_mask = mask[::n_output_frames // n_duplicate][:n_duplicate]
        # mask = np.sort(np.concatenate((mask, dup_mask)))

        data = data[mask]

        flatten = lambda x: [z for y in x for z in y]
        data = flatten(data)

        directory = STORAGE_DIR_POSITIVES if np.any(
            bbs[HAS_COLLISION]) else STORAGE_DIR_NEGATIVES
        filename = str(metadata.id) + ".csv"
        np.savetxt(directory / filename,
                   data,
                   delimiter=',',
                   fmt='%s,%s,%s,%s,%s,%s,%s,%s',
                   comments='')
        stream = ffmpeg.input(item.filepath)
        stream = stream.trim(start_frame=begin + metadata.start_i,
                             end_frame=collision_frame + metadata.start_i,
                             duration=self.clip_len_s)
        stream = ffmpeg.filter(stream,
                               'fps',
                               fps=self.target_fps,
                               round='near')
        stream = ffmpeg.setpts(stream, expr='PTS-STARTPTS')
        stream = stream.output(
            str(STORAGE_DIR_VIDEOS / (str(metadata.id) + '.mp4')))
        stream = ffmpeg.overwrite_output(stream)
        stream.run()
        print(f"Done exporting file {filename}")
        return item
    difference = video_start - dive_start_adjusted

    start_offset = -1 * (difference.total_seconds())

    print "Start Offset: %s " % (start_offset)
    dive_profile = dive_data['dive_profile']

    annotator = Annotator(dive_profile, diver_name=diver_name)

    generate_plot_overlay(dive_profile)

    stream = ffmpeg.input(video_source, acodec='aac')
    audio = stream["a"].filter_("aecho", 0.8, 0.9, 1000, 0.3)
    stream2 = ffmpeg.input('lines.mov')

    stream2 = ffmpeg.setpts(stream2, 'PTS+%s/TB' % (start_offset - 1))
    for i in xrange(0, len(dive_profile)):
        string = annotator.next()
        if (i + 1) < len(dive_profile):
            enable_str = 'between(t,%s,%s)' % (i + start_offset,
                                               i + 1 + start_offset)
        else:
            enable_str = 'gte(t,%s)' % (i + start_offset)
        stream = ffmpeg.drawtext(stream,
                                 string,
                                 x=50,
                                 y=50,
                                 fontfile=fontfile,
                                 fontsize=70,
                                 escape_text=False,
                                 shadowcolor='Black',