3

I'm trying simply to convert a .mov file into .webm using Xuggler, which should work as FFMPEG supports .webm files.

This is my code:

    IMediaReader reader = ToolFactory.makeReader("/home/user/vids/2.mov");
    reader.addListener(ToolFactory.makeWriter("/home/user/vids/2.webm", reader));
    while (reader.readPacket() == null);
    System.out.println( "Finished" );

On running this, I get this error:

[main] ERROR org.ffmpeg - [libvorbis @ 0x8d7fafe0] Specified sample_fmt is not supported.
[main] WARN  com.xuggle.xuggler - Error: could not open codec (../../../../../../../csrc/com/xuggle/xuggler/StreamCoder.cpp:831)
Exception in thread "main" java.lang.RuntimeException: could not open stream com.xuggle.xuggler.IStream@-1921013728[index:1;id:0;streamcoder:com.xuggle.xuggler.IStreamCoder@-1921010088[codec=com.xuggle.xuggler.ICodec@-1921010232[type=CODEC_TYPE_AUDIO;id=CODEC_ID_VORBIS;name=libvorbis;];time base=1/44100;frame rate=0/0;sample rate=44100;channels=1;];framerate:0/0;timebase:1/90000;direction:OUTBOUND;]: Operation not permitted
    at com.xuggle.mediatool.MediaWriter.openStream(MediaWriter.java:1192)
    at com.xuggle.mediatool.MediaWriter.getStream(MediaWriter.java:1052)
    at com.xuggle.mediatool.MediaWriter.encodeAudio(MediaWriter.java:830)
    at com.xuggle.mediatool.MediaWriter.onAudioSamples(MediaWriter.java:1441)
    at com.xuggle.mediatool.AMediaToolMixin.onAudioSamples(AMediaToolMixin.java:89)
    at com.xuggle.mediatool.MediaReader.dispatchAudioSamples(MediaReader.java:628)
    at com.xuggle.mediatool.MediaReader.decodeAudio(MediaReader.java:555)
    at com.xuggle.mediatool.MediaReader.readPacket(MediaReader.java:469)
    at com.mycompany.xugglertest.App.main(App.java:13)
Java Result: 1

Any ideas?

Ali
  • 261,656
  • 265
  • 575
  • 769
  • Did you find a solution to this problem? – Simon Dyson Aug 15 '13 at 11:06
  • 1
    @SimonDyson I didn't find a solution to this error, but I found that calling Xuggler from the command-line worked and didn't bring up this error. The error is only related to the java. So I wrote a command-line bash script which took an input and output file as arguments. From Java I would call up that script, and it would do the conversion. It would output into a log file, and I'd parse the log file to determine what percentage was done. – Ali Aug 15 '13 at 21:28
  • Thanks, think I'm going to follow a similar approach. Beginning to wonder if Xuggler is really offering me any benefits. – Simon Dyson Aug 28 '13 at 15:52
  • Hope I'm not too late with a possible solution – Luke May 09 '14 at 22:33
  • @Luke This question was a long time ago, I can't really test your answer, but it looks well written, so I'll give you a bounty. – Ali May 09 '14 at 23:39
  • Could you mark the answer as accepted, if you consider it to be so? :) – Luke May 22 '14 at 13:19
  • @Luke I can't test your answer, so I'm not sure if it answers the q, but I've given you a bounty – Ali May 23 '14 at 10:29

1 Answers1

3

There's a funky thing going on with Xuggler where it doesn't always allow you to set the sample rate of IAudioSamples. You'll need to use an IAudioResampler.

Took me a while to figure this out. This post by Marty helped a lot, though his code is outdated now.

Here's how you fix it.

.

Before encoding

I'm assuming here that audio input has been properly set up, resulting in an IStreamCoder called audioCoder.

After that's done, you are probably initiating an IMediaWriter and adding an audio stream like so:

final IMediaWriter oggWriter = ToolFactory.makeWriter(oggOutputFile);

// Using stream 1 'cause there is also a video stream.
// For an audio only file you should use stream 0.
oggWriter.addAudioStream(1, 1, ICodec.ID.CODEC_ID_VORBIS, 
                         audioCoder.getChannels(), audioCoder.getSampleRate());

Now create an IAudioResampler:

IAudioResampler oggResampler = IAudioResampler.make(audioCoder.getChannels(), 
                                                   audioCoder.getChannels(), 
                                                   audioCoder.getSampleRate(),
                                                   audioCoder.getSampleRate(),  
                                                   IAudioSamples.Format.FMT_FLT, 
                                                   audioCoder.getSampleFormat());

And tell your IMediaWriter to update to its sample format:

// The stream 1 here is consistent with the stream we added earlier.
oggWriter.getContainer().getStream(1).getStreamCoder().
                         setSampleFormat(IAudioSamples.Format.FMT_FLT);

.

During encoding

You are currently probably initiating an IAudioSamples and filling it with audio data, like so:

IAudioSamples audioSample = IAudioSamples.make(512, audioCoder.getChannels(), 
                                                    audioCoder.getSampleFormat());

int bytesDecoded = audioCoder.decodeAudio(audioSample, packet, offset);

Now initiate an IAudioSamples for our resampled data:

IAudioSamples vorbisSample = IAudioSamples.make(512, audioCoder.getChannels(),
                                                IAudioSamples.Format.FMT_FLT);

Finally, resample the audio data and write the result:

oggResampler.resample(vorbisSample, audioSample, 0);

oggWriter.encodeAudio(1, vorbisSample);  

.

Final thought

Just a hint to get your output files to play well:

  • If you use audio and video within the same container, then audio and video data packets should be written in such an order that the timestamp of each data packet is higher than that of the previous data packet. So you are almost certainly going to need some kind of buffering mechanism that alternates writing audio and video.
Luke
  • 409
  • 3
  • 12
  • this was exactly what I needed, I was trying to mux an mp3 audio file with an mp4 video file into a Webm video and using an ogg resampler definitely worked, i'm still getting glitches in the beginning of the output but that's not a problem – SDIDSA Jan 25 '20 at 12:26