首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >更快地将动画webp转换为mp4

更快地将动画webp转换为mp4
EN

Stack Overflow用户
提问于 2022-01-17 18:28:07
回答 4查看 866关注 0票数 1

在四处搜索之后,我看到有人拥有提出这个,想要一个动态的webp到webm。但这似乎很麻烦。所以我做这个是为了把一个动画的webp转换成mp4或者webm,这是我的live。它需要一些逻辑来将gif转换为视频并加以应用。问题是,这需要一点时间。

我想知道是否有人对如何提高速度有建议?

代码语言:javascript
运行
复制
import os
import moviepy.video.io.ImageSequenceClip

def analyseImage(path):
    '''
    Pre-process pass over the image to determine the mode (full or additive).
    Necessary as assessing single frames isn't reliable. Need to know the mode
    before processing all frames.
    '''
    im = PIL.Image.open(path)
    results = {
        'size': im.size,
        'mode': 'full',
    }
    try:
        while True:
            if im.tile:
                tile = im.tile[0]
                update_region = tile[1]
                update_region_dimensions = update_region[2:]
                if update_region_dimensions != im.size:
                    results['mode'] = 'partial'
                    break
            im.seek(im.tell() + 1)
    except EOFError:
        pass
    return results


def processImage(path):
    '''
    Iterate the animated image extracting each frame.
    '''
    images = []
    mode = analyseImage(path)['mode']

    im = PIL.Image.open(path)

    i = 0
    p = im.getpalette()
    last_frame = im.convert('RGBA')

    try:
        while True:
            print("saving %s (%s) frame %d, %s %s" % (path, mode, i, im.size, im.tile))

            '''
            If the GIF uses local colour tables, each frame will have its own palette.
            If not, we need to apply the global palette to the new frame.
            '''
            if '.gif' in path:
                if not im.getpalette():
                    im.putpalette(p)

            new_frame = PIL.Image.new('RGBA', im.size)

            '''
            Is this file a "partial"-mode GIF where frames update a region of a different size to the entire image?
            If so, we need to construct the new frame by pasting it on top of the preceding frames.
            '''
            if mode == 'partial':
                new_frame.paste(last_frame)

            new_frame.paste(im, (0, 0), im.convert('RGBA'))
            nameoffile = path.split('/')[-1]
            output_folder = path.replace(nameoffile, '')

            name = '%s%s-%d.png' % (output_folder, ''.join(os.path.basename(path).split('.')[:-1]), i)
            print(name)
            new_frame.save(name, 'PNG')
            images.append(name)
            i += 1
            last_frame = new_frame
            im.seek(im.tell() + 1)
    except EOFError:
        pass
    return images



def webp_mp4(filename, outfile):
    images = processImage("%s" % filename)
    fps = 30
    clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(images, fps=fps)
    clip.write_videofile(outfile)
    return [outfile]

webp_mp4(filename, outfile)

它目前的工作方式是,当您运行webp_mp4(filename, outfile)时,它调用调用analyseImageprocessImage。最后,这一切都很好。只是想快点。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2022-01-17 20:00:37

视频转码通常是一项“令人尴尬的并行”任务,而processImage则是在一个大的序列中完成任务。如果processImage是慢的部分,您可以使用multiprocessing.Pool并为每个工作人员(可以在单独的CPU核心上运行)分配自己的帧范围来处理。PIL对象是不可挑选的。,所以您必须编写临时文件,这似乎已经在进行中了。

我对PIL不太了解,所以如果有更好的方法来使用lib,我就不会看到它。也许将每个帧保存为PNG很慢;值得尝试TIF或JPEG。(我会亲自尝试,但是我的Python安装不是在这台笔记本上安装的。)

票数 3
EN

Stack Overflow用户

发布于 2022-02-17 21:24:44

查看代码时的一些优化提示:

  • 您可以在analyseImageprocessImage中从磁盘读取图像。这不是一件大事,因为它只发生一次每个映像,但读取磁盘仍然是一个相对缓慢的操作,所以最好不要做太多的必要。相反,您可以在processImage中打开并将打开的图像传递给analyseImage
  • 处理部分帧的代码所做的工作比它所需要的要多: new_frame = PIL.Image.new('RGBA',im.size)如果模式==‘分部’:new_frame.paste(last_frame) new_frame.paste(im,(0,0),im.convert('RGBA')) (一个新图像,两个粘贴,一个转换) 可能会变成 im = im.convert("RGBA")如果模式==‘分部’:new_frame = last_frame new_frame.paste( im,(0,0),im),否则: new_frame =im (没有新图像,一个粘贴,一个转换)
  • 我怀疑最大的放缓是将每一帧写入磁盘,然后再读取它们。最好将它们保存在内存中(理想情况下,一次只在内存中保存一个)。 imageiomoviepy内部使用的库,它提供了一种实现此功能的方法。您只需使用imageio.get_writer(path)创建一个视频编写器,然后使用writer.append_data(frame_data)依次向其添加帧。 我自己试过了,但是最后我把颜色搞混了,所以我没有工作代码可以提供。不过,作为提示,您可以将PIL图像转换为imageio所期望的原始框架数据,比如numpy.array(im)
票数 1
EN

Stack Overflow用户

发布于 2022-02-17 02:36:06

代码语言:javascript
运行
复制
    threads
      Number of threads to use for ffmpeg. Can speed up the writing of
      the video on multicore computers.

* clip.write_videofile(outfile, threads=4)

您可以设置线程数以提高写入速度。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70745944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档