Audio JavaCV FFmpegFrameGrabber预加载音频

Audio JavaCV FFmpegFrameGrabber预加载音频,audio,ffmpeg,javacv,preload,Audio,Ffmpeg,Javacv,Preload,我有一个应用程序,它使用javacv的FFmpegFrameRecorder将视频数据流到RTMP服务器。我想从一个单独的文件中为这个流添加一些音频-一个我想在重复播放时播放的短声音片段 考虑到声音片段非常短,我想将音频数据预加载到内存中,并在其上循环-这样我就可以避免过多的IO等 我尝试使用javacv的FFmpegFrameGrabber将音频添加到流中,正如多个教程中所述 如果我不尝试预加载/缓存任何音频数据,添加音频效果会非常好,例如: private FFmpegFrameRecord

我有一个应用程序,它使用javacv的FFmpegFrameRecorder将视频数据流到RTMP服务器。我想从一个单独的文件中为这个流添加一些音频-一个我想在重复播放时播放的短声音片段

考虑到声音片段非常短,我想将音频数据预加载到内存中,并在其上循环-这样我就可以避免过多的IO等

我尝试使用javacv的FFmpegFrameGrabber将音频添加到流中,正如多个教程中所述

如果我不尝试预加载/缓存任何音频数据,添加音频效果会非常好,例如:

private FFmpegFrameRecorder frameRecorder;
private FFmpegFrameGrabber frameGrabber;

...
//frameRecorder and frameGrabber setup during initialization
...

public void record(IplImage image) {
        try {
            frameRecorder.record(image);
            Frame frame = frameGrabber.grabFrame();
            if(frame == null) {
                frameGrabber = new FFmpegFrameGrabber("audioFileHere.wav");
                frameGrabber.start();
                frame = frameGrabber.grabFrame();
            }
            frameRecorder.record(frame);
        } catch (FrameRecorder.Exception e) {
            log.error(getMarker(FATAL), "Can't record frame!", e);
        } catch (FrameGrabber.Exception e) {
            log.error(getMarker(FATAL), "Can't record frame!", e);
        }
}
但是,如果我尝试预加载音频数据,则会播放垃圾声音:

private FFmpegFrameRecorder frameRecorder;
private List<FrameData> audioData;

private static final class FrameData {
    public final Buffer[] samples;
    public final Integer sampleRate;
    public final Integer audioChannels;

    //Constructors, getters and setters here
}

...
    //frameRecorder setup during initialization
    audioData = new ArrayList<>();
    FFmpegFrameGrabber audioGrabber = new FFmpegFrameGrabber("audioFileHere.wav");
    try {
        audioGrabber.start();
        Frame frame;
        while ((frame = audioGrabber.grabFrame()) != null) {
            Buffer[] buffers = frame.samples;
            Buffer[] copiedBuffers = new Buffer[buffers.length];
            for (int i = 0; i < buffers.length; i++) {
                copiedBuffers[i] = ((ShortBuffer) buffers[i]).duplicate();
            }
            FrameData frameData = new FrameData(copiedBuffers, frame.sampleRate, frame.audioChannels);
            audioData.add(frameData);
        }
    } catch (FrameGrabber.Exception e) {
        e.printStackTrace();
    }
...

private int frameCount = 0;

public void record(IplImage image) {
    frameCount++;
    try {
        FrameData frameData = audioData.get(frameCount % audioData.size());
        frameRecorder.record(image);
        frameRecorder.record(frameData.sampleRate, frameData.audioChannels, frameData.samples);
    } catch (FrameRecorder.Exception e) {
        log.error(getMarker(FATAL), "Can't record frame!", e);
    }
}
私有FFmpegFrameRecorder帧记录器;
私人名单音频数据;
私有静态最终类框架数据{
公共最终缓冲区[]样本;
公共最终整数采样器;
公共音频频道;
//这里的构造函数、getter和setter
}
...
//初始化期间的frameRecorder设置
audioData=新的ArrayList();
FFmpegFrameGrabber audioGrabber=新的FFmpegFrameGrabber(“audioFileHere.wav”);
试一试{
audioGrabber.start();
框架;
而((frame=audioGrabber.grabFrame())!=null){
Buffer[]buffers=frame.samples;
缓冲区[]复制缓冲区=新缓冲区[buffers.length];
对于(int i=0;i
注意:我必须深度复制帧对象,因为FFmpegFrameGrabber.grabFrame()会回收单个帧对象


有人能解释一下为什么这不起作用和/或我如何才能达到预期的结果吗?

我在我的特定代码示例中找到了解决方案。ShortBuffer.duplicate()不进行深度复制,因此导致了问题。相反,我必须创建一个新的ShortBuffer并复制内容。

我在特定的代码示例中找到了解决方案。ShortBuffer.duplicate()不进行深度复制,因此导致了问题。相反,我必须创建一个新的ShortBuffer并复制内容