Мой сценарий генерирует видео из некоторых изображений .jpg
, которые отлично работают. Кроме того, он добавляет аудиопоток из уже существующего файла .flac
. Код работает довольно хорошо с небольшими аудиофайлами. Но, используя мой фактический файл, который находится вокруг 1GB
я получаю следующее предупреждение/исключение:Декодирование большого аудиофайла usind Xuggler
22:00:03.366 [main] WARN com.xuggle.xuggler - error: not enough memory in internal frame buffer (../../../../../../../csrc/com/xuggle/xuggler/StreamCoder.cpp:1768)
Exception in thread "main" java.lang.RuntimeException: failed to encode audio
at com.xuggle.mediatool.MediaWriter.encodeAudio(MediaWriter.java:855)
at diaporama.Renderer.renderVideo(Renderer.java:129)
at diaporama.Renderer.<init>(Renderer.java:32)
at Run.main(Run.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Я предполагаю, что не хватает памяти для буферизации большого аудиофайла. Но я пытаюсь найти решение для этого. Есть ли у кого-нибудь какие-либо предложения о том, как надежно работать с большими аудиофайлами в этом отношении?
Это мой код:
private void renderVideo() {
final IMediaWriter writer = ToolFactory.makeWriter(this.outputFileName);
// video stream
writer.addVideoStream(0, 0, this.videoCodec, this.width, this.height);
// audio stream
IContainer containerAudio = IContainer.make();
containerAudio.open(this.audioFile.getPath(), IContainer.Type.READ, null);
IStreamCoder coderAudio = containerAudio.getStream(0).getStreamCoder();
if (coderAudio.open(null, null) < 0)
throw new RuntimeException("Cannot open audio coder");
writer.addAudioStream(1, 0, this.audioCodec, coderAudio.getChannels(), coderAudio.getSampleRate());
// video rendering
// ... video rendering takes place here ...
// audio rendering
System.out.println("Adding audio file: " + this.audioFile.getPath() + " to stream");
// read audio file and create stream
IPacket packetaudio = IPacket.make();
IAudioSamples samples;
while (containerAudio.readNextPacket(packetaudio) >= 0) {
/*
* We allocate a set of samples with the same number of channels as the
* coder tells us is in this buffer.
*
* We also pass in a buffer size (1024 in our example), although Xuggler
* will probably allocate more space than just the 1024 (it's not important why).
*/
samples = IAudioSamples.make(1024, coderAudio.getChannels());
/*
* A packet can actually contain multiple sets of samples (or frames of samples
* in audio-decoding speak). So, we may need to call decode audio multiple
* times at different offsets in the packet's data. We capture that here.
*/
int offset = 0;
/*
* Keep going until we've processed all data
*/
while (offset < packetaudio.getSize()) {
int bytesDecoded = coderAudio.decodeAudio(samples, packetaudio, offset);
if (bytesDecoded < 0)
throw new RuntimeException("got error decoding audio in: " + this.audioFile);
offset += bytesDecoded;
/*
* Some decoder will consume data in a packet, but will not be able to construct
* a full set of samples yet. Therefore you should always check if you
* got a complete set of samples from the decoder
*/
if (samples.isComplete()) {
writer.encodeAudio(1, samples);
}
}
}
coderAudio.close();
containerAudio.close();
writer.close();
}