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

如何将字节帧无损编码为MP4并还原为原字节数据(Python)

无损将字节数据编码为MP4并还原的实现方案

核心思路

要实现字节数据的无损存储与还原,关键是禁止使用任何有损视频编码,必须采用像素级无损的编码格式(如FFV1、LAGS),同时确保原字节数据完整嵌入视频帧中,解码时能1:1提取。另外需要记录原文件的关键元数据(字节长度、文件名、格式),否则无法准确还原原文件。

一、将字节数据编码为MP4

步骤说明

  1. 计算单帧最大可容纳字节数:(1920,1080)的RGB24格式帧(每个像素3字节)总容量为 1920*1080*3 = 6220800 字节。
  2. 将原文件字节数据拆分为若干块,每块不超过单帧容量,最后一块用0x00填充至帧容量。
  3. 将每个字节块转换为RGB帧(把字节值直接映射到RGB三个通道,视觉上为灰度帧,不影响数据完整性)。
  4. 用无损视频编码格式将帧写入MP4文件,同时保存原文件的元数据(如字节长度、文件名)。

示例代码

import cv2
import numpy as np
import os

def encode_bytes_to_mp4(raw_data, output_mp4, original_file_info):
    # 单帧容量(RGB24格式)
    frame_width = 1920
    frame_height = 1080
    frame_byte_size = frame_width * frame_height * 3
    
    # 拆分字节数据为帧块,不足补0
    data_blocks = []
    for i in range(0, len(raw_data), frame_byte_size):
        block = raw_data[i:i+frame_byte_size]
        if len(block) < frame_byte_size:
            block += b'\x00' * (frame_byte_size - len(block))
        data_blocks.append(block)
    
    # 初始化视频写入器,使用FFV1无损编码
    fourcc = cv2.VideoWriter_fourcc(*'FFV1')
    fps = 1  # 帧率不影响数据,设为1即可
    video_writer = cv2.VideoWriter(output_mp4, fourcc, fps, (frame_width, frame_height))
    
    # 将每个块转为RGB帧并写入
    for block in data_blocks:
        # 把字节转为numpy数组,再reshape为RGB帧
        frame_data = np.frombuffer(block, dtype=np.uint8).reshape((frame_height, frame_width, 3))
        video_writer.write(frame_data)
    
    video_writer.release()
    
    # 保存原文件元数据(用于解码)
    with open(f"{output_mp4}.meta", 'w') as f:
        f.write(f"filename: {original_file_info['filename']}\n")
        f.write(f"original_size: {original_file_info['original_size']}\n")

# 调用示例
files_path = "./your_files_dir"
file = "example.zip"
with open(f'{files_path}/{file}','rb') as f:
    raw_data = f.read()

original_info = {
    "filename": file,
    "original_size": len(raw_data)
}
encode_bytes_to_mp4(raw_data, "output.mp4", original_info)

二、从MP4解码还原原字节数据

步骤说明

  1. 读取MP4文件的每一帧,将帧转换回字节数组。
  2. 拼接所有帧的字节数据,根据保存的元数据截断到原文件的实际长度。
  3. 将截断后的字节数据写入原格式文件,验证数据完整性(可通过MD5校验)。

示例代码

import cv2
import numpy as np
import hashlib

def decode_mp4_to_bytes(input_mp4, output_dir):
    # 读取元数据
    with open(f"{input_mp4}.meta", 'r') as f:
        meta = dict(line.strip().split(': ') for line in f)
    original_filename = meta['filename']
    original_size = int(meta['original_size'])
    
    # 读取视频帧
    cap = cv2.VideoCapture(input_mp4)
    all_bytes = b''
    
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        # 将帧转为字节数组
        frame_bytes = frame.tobytes()
        all_bytes += frame_bytes
    
    cap.release()
    
    # 截断到原文件长度,去掉填充的0
    raw_data = all_bytes[:original_size]
    
    # 写入原文件
    output_path = os.path.join(output_dir, original_filename)
    with open(output_path, 'wb') as f:
        f.write(raw_data)
    
    # 可选:MD5校验(和原文件对比)
    def calculate_md5(file_path):
        md5 = hashlib.md5()
        with open(file_path, 'rb') as f:
            for chunk in iter(lambda: f.read(4096), b''):
                md5.update(chunk)
        return md5.hexdigest()
    
    original_md5 = calculate_md5(os.path.join(files_path, original_filename))
    restored_md5 = calculate_md5(output_path)
    print(f"原文件MD5: {original_md5}")
    print(f"还原文件MD5: {restored_md5}")
    print(f"数据是否无损: {original_md5 == restored_md5}")

# 调用示例
decode_mp4_to_bytes("output.mp4", "./restored_files")

关键注意事项

  • 必须使用无损编码:示例中用的FFV1是FFmpeg提供的无损视频编码,确保像素数据不被压缩修改。避免使用H.264、MJPG等有损编码,否则字节数据会被篡改。
  • 元数据不可少:原文件的字节长度是还原的关键,否则无法区分有效数据和填充的0字节。也可以把元数据嵌入第一帧的前N个字节中,避免单独保存元文件。
  • 帧格式选择:选用RGB24是因为每个像素对应3字节,计算和转换简单;也可以用灰度格式(单字节),但单帧容量会减半(1920*1080=2073600字节),需要更多帧来存储大文件。

内容的提问来源于stack exchange,提问作者vishnu vardhan Gowd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:32:10