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

如何使用Java Media Framework(JMF)将BufferedImage数组生成视频

使用JMF将BufferedImage数组导出为视频的实现方案

首先确认项目已正确导入JMF依赖,且运行环境已配置JMF的native库(部分编码格式需要系统层面的编码支持)。

1. 配置可自定义的输出参数

首先定义你需要的分辨率、帧率、输出格式等可配置项,示例配置如下:

// 可自定义配置项
int targetWidth = 1280; // 输出视频宽度
int targetHeight = 720; // 输出视频高度
float frameRate = 30f; // 输出帧率
File outputFile = new File("output.avi"); // 输出文件路径,格式可根据需求修改为mov等JMF支持的格式

如果你的BufferedImage分辨率和目标分辨率不一致,需要先做缩放处理,可通过Graphics2D绘制缩放后的图像:

public BufferedImage resizeImage(BufferedImage source, int targetWidth, int targetHeight) {
    BufferedImage resized = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = resized.createGraphics();
    g2d.drawImage(source, 0, 0, targetWidth, targetHeight, null);
    g2d.dispose();
    return resized;
}

2. 构造JMF可识别的视频格式

创建对应参数的VideoFormat对象,匹配你的输出配置:

VideoFormat videoFormat = new RGBFormat(
    new Dimension(targetWidth, targetHeight), // 分辨率
    Format.NOT_SPECIFIED,
    byte[].class,
    frameRate,
    24, // 位深
    0xff0000, 0xff00, 0xff, // RGB掩码
    1, // 像素步长
    Format.NOT_SPECIFIED,
    Format.TRUE,
    Format.NOT_SPECIFIED
);

3. 初始化JMF处理器与输出链路

通过JMF的Processor和DataSink创建输出链路,绑定输出文件:

Processor processor = Manager.createProcessor(new Format[]{videoFormat});
processor.configure();
// 等待处理器配置完成
while (processor.getState() != Processor.Configured) {
    Thread.sleep(10);
}
// 设置输出内容为纯视频
processor.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.MSVIDEO));
// 配置轨道格式
TrackControl[] trackControls = processor.getTrackControls();
if (trackControls != null && trackControls.length > 0) {
    trackControls[0].setFormat(videoFormat);
}
processor.realize();
while (processor.getState() != Processor.Realized) {
    Thread.sleep(10);
}
// 创建输出数据汇
DataSink dataSink = Manager.createDataSink(processor.getDataOutput(), new MediaLocator(outputFile.toURI().toURL()));
dataSink.open();
processor.start();
dataSink.start();

4. 逐帧写入BufferedImage数组

遍历你存储的BufferedImage数组,将每个图像转换为JMF的Buffer对象写入处理器:

// 假设你的BufferedImage数组为frameArray
for (BufferedImage frame : frameArray) {
    // 先缩放到目标分辨率
    BufferedImage resizedFrame = resizeImage(frame, targetWidth, targetHeight);
    // 提取图像RGB数据
    int[] rgbData = resizedFrame.getRGB(0, 0, targetWidth, targetHeight, null, 0, targetWidth);
    byte[] bufferData = new byte[targetWidth * targetHeight * 3];
    int index = 0;
    for (int rgb : rgbData) {
        bufferData[index++] = (byte) (rgb >> 16); // R
        bufferData[index++] = (byte) (rgb >> 8); // G
        bufferData[index++] = (byte) rgb; // B
    }
    // 构造JMF Buffer
    Buffer buffer = new Buffer();
    buffer.setData(bufferData);
    buffer.setFormat(videoFormat);
    buffer.setLength(bufferData.length);
    buffer.setOffset(0);
    // 按帧间隔计算时间戳,保证播放速度均匀,单位为微秒
    buffer.setTimeStamp((long) (frameIndex * (1000000 / frameRate)));
    // 写入处理器
    processor.getInputTrack(0).writeBuffer(buffer);
}
// 写入完成后关闭资源
processor.stop();
dataSink.stop();
dataSink.close();
processor.close();

注意事项

  • 若需要更换输出格式,只需修改FileTypeDescriptor的参数,JMF原生支持MSVIDEO(AVI)、QUICKTIME(MOV)、MPEG等格式,选择对应枚举值即可
  • 若出现编码不支持的报错,可安装JMF的可选编码包扩展支持的格式范围
  • JMF本身对高分辨率视频支持有限,建议分辨率设置在1920*1080以内避免编码错误
  • 上述代码省略了异常捕获逻辑,实际使用时需要对JMF相关操作捕获IOException、NoProcessorException、InterruptedException等受检异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 03:30:05