You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用FFmpeg将YUV420格式视频文件转换为16位?

解决12位YUV转16位的方法

一、FFmpeg正确命令

你的原命令无效的原因有三个:

  1. -sample_fmt s16是音频采样格式参数,对视频完全不起作用;
  2. 输入像素格式指定错误:你用了8位的yuv420p,但实际输入是12位YUV,必须指定对应的12位格式(比如yuv420p12le小端、yuv420p12be大端);
  3. 缺少-f rawvideo参数,FFmpeg无法识别输入是原始无封装的YUV流。

正确命令示例

假设你的输入是小端12位YUV420(最常见的12位格式),执行:

ffmpeg -f rawvideo -video_size 352x288 -pixel_format yuv420p12le -i input.yuv -pixel_format yuv420p16le output.yuv

如果输入是大端格式,把yuv420p12le换成yuv420p12be即可;输出的16位格式也可以换成yuv422p16le等其他16位YUV格式,只要把命令里的-pixel_format对应参数替换就行。

执行后你会发现输出文件大小明显变大:原20帧12位YUV420的大小是352*288*1.5*12/8*20=4561920字节,转成16位YUV420后大小是352*288*1.5*2*20=6082560字节,以此验证转换成功。

二、Python手动转换(适合小文件)

因为你的视频只有20帧,规模很小,可以直接读取原始二进制数据,将每个12位像素值扩展为16位(左移4位填充高位0,保证数据精度),再按16位YUV格式写入。

以下是针对打包式12位YUV420(每3字节存储2个12位像素)的示例代码:

import os

# 基础配置
WIDTH = 352
HEIGHT = 288
FRAME_COUNT = 20

# 计算各分量的字节数
INPUT_FRAME_SIZE = WIDTH * HEIGHT * 9 // 4  # 12位YUV420每帧总字节数
OUTPUT_FRAME_SIZE = WIDTH * HEIGHT * 3       # 16位YUV420每帧总字节数

def convert_12bit_to_16bit(raw_data):
    """将打包的12位像素数据转成16位小端格式"""
    output = bytearray()
    # 每3字节处理2个12位像素
    for i in range(0, len(raw_data), 3):
        # 第一个像素:低8位+高4位,左移4位补0到16位
        pix1 = (raw_data[i] | ((raw_data[i+1] & 0x0F) << 8)) << 4
        # 第二个像素:低8位+高4位,左移4位补0到16位
        pix2 = (raw_data[i+2] | ((raw_data[i+1] >> 4) << 8)) << 4
        # 按小端写入16位数据
        output.extend([pix1 & 0xFF, (pix1 >> 8) & 0xFF])
        output.extend([pix2 & 0xFF, (pix2 >> 8) & 0xFF])
    return output

with open("input.yuv", "rb") as f_in, open("output.yuv", "wb") as f_out:
    for _ in range(FRAME_COUNT):
        frame = f_in.read(INPUT_FRAME_SIZE)
        if not frame:
            break
        
        # 拆分Y、U、V分量
        y_len = WIDTH * HEIGHT * 3 // 2  # Y分量字节数
        u_len = WIDTH * HEIGHT * 3 // 8  # U分量字节数
        v_len = u_len
        
        y_data = frame[:y_len]
        u_data = frame[y_len:y_len+u_len]
        v_data = frame[y_len+u_len:]
        
        # 转换各分量并写入
        f_out.write(convert_12bit_to_16bit(y_data))
        f_out.write(convert_12bit_to_16bit(u_data))
        f_out.write(convert_12bit_to_16bit(v_data))

如果你的输入是平面式12位YUV(每个分量单独存储,每个像素用2字节存12位数据),只需要修改convert_12bit_to_16bit函数,直接读取每个2字节的12位值,左移4位后写入即可。

内容的提问来源于stack exchange,提问作者IanMurphy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:55:16