示例#1
0
def save_out(tracks, outfile=None, filetype='mp4'):

    out = []

    vids = [t for t in tracks if t['type'] == 'vid']
    texts = [t for t in tracks if t['type'] == 'text']

    for v in vids:
        c = VideoFileClip(v['content']).subclip(v['in'],
                                                v['in'] + v['duration'])
        c = c.set_start(v['start'])
        out.append(c)

    size = out[0].size

    for t in texts:
        c = create_sub(t['content'], size, rect_offset=195, min_height=55)
        c = c.set_start(t['start'])
        c = c.set_duration(t['duration'])
        out.append(c)

    final_clip = CompositeVideoClip(out)
    if outfile is None:
        outfile = 'msg_' + str(int(time.time())) + '.mp4'
    if filetype == 'gif':
        outfile = outfile.replace('.mp4', '.gif')
        final_clip.speedx(1.7).write_gif(outfile, fps=7, loop=1)
    else:
        final_clip.write_videofile(outfile, fps=24, codec='libx264')
    return outfile
示例#2
0
def save_out(tracks, outfile=None, filetype='mp4'):

    out = []

    vids = [t for t in tracks if t['type'] == 'vid']
    texts = [t for t in tracks if t['type'] == 'text']

    for v in vids:
        c = VideoFileClip(v['content']).subclip(v['in'], v['in'] + v['duration'])
        c = c.set_start(v['start'])
        out.append(c)

    size = out[0].size

    for t in texts:
        c = create_sub(t['content'], size, rect_offset=195, min_height=55)
        c = c.set_start(t['start'])
        c = c.set_duration(t['duration'])
        out.append(c)

    final_clip = CompositeVideoClip(out)
    if outfile is None:
        outfile = 'msg_' + str(int(time.time())) + '.mp4'
    if filetype == 'gif':
        outfile = outfile.replace('.mp4', '.gif')
        final_clip.speedx(1.7).write_gif(outfile, fps=7, loop=1)
    else:
        final_clip.write_videofile(outfile, fps=24, codec='libx264')
    return outfile
示例#3
0
class Clip:
    _cache: dict[Path, VideoFileClip] = {}

    def __init__(self, meta: ClipMeta):
        self.meta = meta
        if meta.path not in Clip._cache:
            Clip._cache[meta.path] = VideoFileClip(str(meta.path))
        self.video_file_clip = Clip._cache[meta.path]

    def cut(self):
        if self.meta.start is not None and self.meta.end is not None:
            logger.info(
                '%s: Cutting %s -> %s',
                self.meta.path,
                self.meta.start,
                self.meta.end,
            )
            self.video_file_clip = self.video_file_clip.subclip(
                self.meta.start.total_seconds(), self.meta.end.total_seconds())

    def set_fps(self):
        self.video_file_clip = self.video_file_clip.set_fps(self.video_fps)

    def resize(self, width: int, height: int):
        current_width = self.video_file_clip.w
        current_height = self.video_file_clip.h
        current_aspect_ratio = current_width / current_height
        new_aspect_ratio = width / height
        if current_width == width and current_height == height:
            logger.info('%s: Resizing not necessary', self.meta.path)
            return
        crop_x: float = 0
        crop_y: float = 0
        if new_aspect_ratio > current_aspect_ratio:
            new_width: float = width
            new_height: float = round(new_width / current_aspect_ratio)
            crop_y = (new_height - height) / 2
        elif new_aspect_ratio < current_aspect_ratio:
            new_height = height
            new_width = round(new_height * current_aspect_ratio)
            crop_x = (new_width - width) / 2
        else:
            new_width = width
            new_height = height

        logger.info(
            '%s: Resizing from %f x %f [%f] to %f x %f [%f] ',
            self.meta.path,
            current_width,
            current_height,
            current_aspect_ratio,
            new_width,
            new_height,
            new_aspect_ratio,
        )
        self.video_file_clip = self.video_file_clip.resize(
            (new_width, new_height))

        if crop_x > 0 or crop_y > 0:
            logger.info(
                '%s: Cropping +%f+%f',
                self.meta.path,
                crop_x,
                crop_y,
            )
            self.video_file_clip = self.video_file_clip.crop(x1=crop_x,
                                                             y1=crop_y,
                                                             width=width,
                                                             height=height)

    def add_subtitles(
        self,
        subtitles_path: Path,
        color: str = DEFAULT_SUBTITLE_COLOR,
        font: str = DEFAULT_SUBTITLE_FONT,
        fontsize: int = DEFAULT_SUBTITLE_FONTSIZE,
    ):
        """Currently unused"""
        def subtitle_text_clip_factory(text: str) -> TextClip:
            return TextClip(text, font, fontsize, color)

        subtitles_clip = SubtitlesClip(subtitles_path,
                                       subtitle_text_clip_factory)
        self.video_file_clip = CompositeVideoClip(
            [self.video_file_clip, subtitles_clip])

    def prepend_intertitle(
        self,
        size: Optional[Size] = None,
        color: str = DEFAULT_INTERTITLE_COLOR,
        font: str = DEFAULT_INTERTITLE_FONT,
        fontsize: int = DEFAULT_INTERTITLE_FONTSIZE,
        position: str = DEFAULT_INTERTITLE_POSITION,
        duration: int = DEFAULT_INTERTITLE_DURATION,
    ):
        if not self.meta.text:
            logger.warning('%s: Missing intertitle text')
            return
        logger.info('%s: Intertitle "%s"', self.meta.path, self.meta.text)
        if not size:
            size = Size(width=self.video_file_clip.w,
                        height=self.video_file_clip.h)
        text_clip = TextClip(
            self.meta.text.replace('|', '\n'),
            size=(size.width * INTERTITLE_TEXT_WIDTH_FACTOR, None),
            color=color,
            font=font,
            fontsize=fontsize,
            method='caption',
            align='center',
        )
        composite_clip = CompositeVideoClip([text_clip.set_pos(position)],
                                            (size.width, size.height))
        intertitle_clip = composite_clip.subclip(0, duration)
        self.video_file_clip = concatenate_videoclips(
            [intertitle_clip, self.video_file_clip], method='compose')

    def fadeout(self, duration: float):
        self.video_file_clip = self.video_file_clip.fadeout(duration / 1000)

    def speed(self, factor: float):
        self.video_file_clip = self.video_file_clip.speedx(factor=factor)