【问题标题】:javacv merging image and mp3 creates a mp4 longer than the original mp3javacv 合并图像和 mp3 创建的 mp4 比原始 mp3 长
【发布时间】:2020-05-10 01:19:44
【问题描述】:

我正在使用下面的代码来合并一个 mp3 和一个图像

IplImage ipl = cvLoadImage(path2ImageFile);
int height = ipl.height();
int width = ipl.width();
if(height%2!=0) height = height+1;
if(width%2!=0) width = width+1;

OpenCVFrameConverter.ToIplImage grabberConverter = new OpenCVFrameConverter.ToIplImage();  
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(path2OutputFile,width,height); 
FrameGrabber audioFileGrabber = new FFmpegFrameGrabber(path2AudioFile);
try 
{  
    audioFileGrabber.start();

    recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264 );//AV_CODEC_ID_VORBIS
    recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);//AV_CODEC_ID_MP3 //AV_CODEC_ID_AAC

    recorder.setFormat("mp4");  
    recorder.setAudioChannels(2);
    recorder.start();  

    Frame frame = null;
    //audioFileGrabber.getFrameNumber()
    while ((frame = audioFileGrabber.grabFrame())!=null) 
    {   recorder.record(grabberConverter.convert(ipl));  
        recorder.record(frame);
    }

    recorder.stop();  
    audioFileGrabber.stop();
 }  

这会产生一个 mp4,但要长约 1 分半钟。
为什么会这样?
有什么办法可以解决这个问题吗?

【问题讨论】:

  • 这额外的 1 分半钟包含什么(例如: 任何图片或声音)?

标签: java video mp3 mp4 javacv


【解决方案1】:

这是一个很好的解决问题。 IMO,问题似乎有两个原因

  • 这种情况下video的帧率需要和Audio的帧率一样,所以没有时间增加
  • 写入时的音频帧应写入相同的时间戳

以下是适合我的最终代码

import org.bytedeco.ffmpeg.global.*;
import org.bytedeco.javacv.*;


public class AudioExample {
    public static void main(String[] args) {
        String path2ImageFile = "WhatsApp Image 2018-12-29 at 21.54.58.jpeg";
        String path2OutputFile = "test.mp4";
        String path2AudioFile = "GMV_M_Brice_English_Greeting-Menus.mp3";

        FFmpegFrameGrabber imageFileGrabber = new FFmpegFrameGrabber(path2ImageFile);
        FFmpegFrameGrabber audioFileGrabber = new FFmpegFrameGrabber(path2AudioFile);
        try {
            audioFileGrabber.start();
            imageFileGrabber.start();

            FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(path2OutputFile,
                    imageFileGrabber.getImageWidth(), imageFileGrabber.getImageHeight());

            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);//AV_CODEC_ID_VORBIS
            recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);//AV_CODEC_ID_MP3 //AV_CODEC_ID_AAC
            recorder.setSampleRate(audioFileGrabber.getSampleRate());
            recorder.setFrameRate(audioFileGrabber.getAudioFrameRate());
            recorder.setVideoQuality(1);
            recorder.setFormat("mp4");
            recorder.setAudioChannels(2);
            recorder.start();

            Frame frame = null;

            Frame imageFrame = imageFileGrabber.grab();
            while ((frame = audioFileGrabber.grab()) != null) {
                recorder.setTimestamp(frame.timestamp);
                recorder.record(imageFrame);
                recorder.record(frame);
            }
            recorder.stop();
            audioFileGrabber.stop();
            imageFileGrabber.stop();
        } catch (FrameRecorder.Exception | FrameGrabber.Exception e) {
            e.printStackTrace();
        }
    }
}

我删除了图像的 opencv,因为我们也可以使用另一个帧抓取器来获取图像作为帧。您还可以看到生成的音频与 mp3 大小相同

尝试 #2

由于第一次尝试对视频和音频使用相同的帧率,这导致了一些问题,我想修复帧率,然后在顶部交错音频

import org.bytedeco.ffmpeg.global.*;
import org.bytedeco.javacv.*;


public class AudioExample {
    public static void main(String[] args) {
        String path2ImageFile = "/Users/tarunlalwani/Downloads/WhatsApp Image 2018-12-29 at 21.54.58.jpeg";
        String path2OutputFile = "/Users/tarunlalwani/Downloads/test.mp4";
        String path2AudioFile = "/Users/tarunlalwani/Downloads/GMV_M_Brice_English_Greeting-Menus.mp3";

        FFmpegFrameGrabber imageFileGrabber = new FFmpegFrameGrabber(path2ImageFile);
        FFmpegFrameGrabber audioFileGrabber = new FFmpegFrameGrabber(path2AudioFile);
        try {
            audioFileGrabber.start();
            imageFileGrabber.start();

            FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(path2OutputFile,
                    imageFileGrabber.getImageWidth(), imageFileGrabber.getImageHeight());

            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);//AV_CODEC_ID_VORBIS
            recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);//AV_CODEC_ID_MP3 //AV_CODEC_ID_AAC
            recorder.setSampleRate(audioFileGrabber.getSampleRate());
            int frameRate = 30;
            recorder.setFrameRate(frameRate);
            recorder.setFormat("mp4");
            recorder.setAudioChannels(2);
            recorder.start();

            Frame frame = null;

            Frame imageFrame = imageFileGrabber.grab();
            int frames = (int)((audioFileGrabber.getLengthInTime() / 1000000f) * frameRate) + 1;
            int i = 0;

            //create video using fixed images and framerate
            while (i ++ <frames) {
                recorder.record(imageFrame);
            }

            // Add audio to given timestamps
            while ((frame = audioFileGrabber.grabFrame()) != null) {
                recorder.setTimestamp(frame.timestamp);
                recorder.record(frame);
            }

            recorder.stop();
            audioFileGrabber.stop();
            imageFileGrabber.stop();
        } catch (FrameRecorder.Exception | FrameGrabber.Exception e) {
            e.printStackTrace();
        }
    }
}

【讨论】:

  • 谢谢。它在 VLC 中工作,但在标准的 windows 媒体播放器中可以听到声音,但屏幕是黑色的。我正在使用 Windows 10。
  • 我没有要测试的窗口。这可能与选择的视频编解码器有关吗?
  • 在 javacv 论坛上,他们说这可能与我录制的帧数太少或太多有关。我应该只记录与最大帧速率一样多的帧,显然 setFrameRate 函数设置了最大帧速率。实际使用 setTimestamp 设置帧时设置实际帧速率。 groups.google.com/forum/#!topic/javacv/Wr28ZNq2se0 不幸的是,我仍然很难理解这一切:( 生成的视频......工作和不工作取决于......我不知道到底是什么...... :(
  • 很多事情都不清楚,因为没有文档说明您应该理想地这样做或那样做。这更多的是通过命中 n 试验来学习
  • @Para,请参阅更新后的答案。我希望新代码对您有所帮助。你可以在这个中使用固定的 frameRate
猜你喜欢
  • 2019-11-22
  • 2013-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 2021-02-07
  • 2018-09-23
  • 1970-01-01
相关资源
最近更新 更多