使用 ffmpeg 和子进程获取字节输出

问题描述 投票:0回答:1

我正在从网站下载一些图像并用它制作视频。我不想将视频保存到文件中,然后读取它,以便可以通过 POST 请求发送它。我希望统一此过程并下载 > 制作视频 > 获取输出字节 > POST。

def convert_images_to_video():
    #output_video = "output.mp4"

    data = get_radar_images("a")
    if not data:
        return False
    
    ffmpeg_cmd = [
        "ffmpeg",
        "-framerate",
        "2",  # Input frame rate (adjust as needed)
        "-f",
        "image2pipe",
        "-vcodec",
        "png",
        "-i",
        "-",  # Input from pipe
        "-vf",  # Video filter
        "fps=30",  # Output frame rate (adjust as needed)
        "-c:v",
        "libx264",  # Video codec (h.264)
        "-vf",  # Additional video filters
        "pad=ceil(iw/2)*2:ceil(ih/2)*2",  # Padding and resolution adjustment
        "-profile:v",
        "high",  # H.264 profile
        "-level",
        "3.0",  # H.264 level
        "-pix_fmt",
        "yuv420p",  # Pixel format
        "-brand",
        "mp42",
        "-movflags",
        "frag_keyframe",  # Branding
        "-f",
        "mp4",
        "-",
    ]


    ffmpeg_process = subprocess.Popen(
        ffmpeg_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    radar_images = data.get("list")[::-1]

    for image in radar_images:
        img_url = f"https://mycoolweb.com/coolimages/{image}"
        content = requests.get(img_url).content
        ffmpeg_process.stdin.write(content)

    ffmpeg_process.stdin.close()
    ffmpeg_process.terminate()

    ffmpeg_process.wait()
    video_bytes = ffmpeg_process.stdout.read()

    print(video_bytes)

通过执行此操作并执行

python app.py
使进程挂在那里,根本没有任何输出。我尝试将
universal_newlines=True
添加到
subprocess.Popen
但返回
TypeError: write() argument must be str, not bytes
异常。

由于我正在处理图像,所以它不起作用

image.decode("utf-8")
。我已经尝试了一段时间并阅读了ffmpeg管道上的文档但无法让它工作。

python ffmpeg pipe
1个回答
0
投票

我用Pillow来解决这个问题。

from PIL import Image
import io
from subprocess import PIPE

...

def convert_images_to_video():

...

    ffmpeg_pipe = subprocess.Popen(ffmpeg_cmd, stdin=PIPE, stdout=PIPE)

    for img_url in urls:
        content = requests.get(img_url).content
        buf = io.BytesIO(content)
        img = Image.open(buf)
        img.save(ffmpeg_pipe.stdin, 'PNG')
        buf.close()

    ffmpeg_pipe.stdin.close()
    video_bytes = ffmpeg_pipe.stdout.read()
    ffmpeg_pipe.terminate()
    ffmpeg_pipe.wait()

    # Save the video locally to verify
    with open("output.mp4", 'wb') as f:
        f.write(video_bytes)

    print(video_bytes)

另请注意,您需要在关闭

stdin
之后但在管道上调用
terminate
之前从子进程管道中读取字节。

© www.soinside.com 2019 - 2024. All rights reserved.