使用 Xuggler 进行音频转换

发布于 2024-11-27 10:46:59 字数 4858 浏览 5 评论 0原文

我正在尝试使用 Java 中的 Xuggler 将 aac/wav/wma 音频文件转换为 mp3。

不幸的是,我的质量损失很大。我的输入文件大小约为 7MB,输出文件大小仅为 1.5MB。

采样率设置为44100Hz,还有其他参数需要设置吗?

谢谢您的回答。

  if (args.length <= 1)
        throw new IllegalArgumentException("must pass an input filename and output filename as argument");

    IMediaWriter writer = ToolFactory.makeWriter(args[1]);

    String filename = args[0];

    // Create a Xuggler container object
    IContainer container = IContainer.make();

    // Open up the container
    if (container.open(filename, IContainer.Type.READ, null) < 0)
        throw new IllegalArgumentException("could not open file: " + filename);

    // query how many streams the call to open found
    int numStreams = container.getNumStreams();

    // and iterate through the streams to find the first audio stream
    int audioStreamId = -1;
    IStreamCoder audioCoder = null;
    for(int i = 0; i < numStreams; i++)
    {
        // Find the stream object
        IStream stream = container.getStream(i);
        // Get the pre-configured decoder that can decode this stream;
        IStreamCoder coder = stream.getStreamCoder();

        if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO)
        {
            audioStreamId = i;
            audioCoder = coder;
            audioCoder.setBitRate(container.getBitRate());

            break;
        }
    }

    if (audioStreamId == -1)
        throw new RuntimeException("could not find audio stream in container: "+filename);

    /* We read only AAC file for the moment */
    if(audioCoder.getCodecID() != ICodec.ID.CODEC_ID_AAC 
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WAVPACK 
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WMAV1
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WMAV2
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WMAPRO
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WMAVOICE)
    {
        System.out.println("Read only AAC, WAV or WMA files");
        System.exit(1);
    }

    audioCoder.setSampleFormat(IAudioSamples.Format.FMT_S16);
    /*
     * Now we have found the audio stream in this file.  Let's open up our decoder so it can
     * do work.
     */
    if (audioCoder.open() < 0)
        throw new RuntimeException("could not open audio decoder for container: "+filename);

    int streamIndex = writer.addAudioStream(0, 0, audioCoder.getChannels(), audioCoder.getSampleRate());


    System.out.println("audio Frame size : "+audioCoder.getAudioFrameSize());


    /*
     * Now, we start walking through the container looking at each packet.
     */
    IPacket packet = IPacket.make();

    while(container.readNextPacket(packet) >= 0)
    {
        /*
         * Now we have a packet, let's see if it belongs to our audio stream
         */
        if (packet.getStreamIndex() == audioStreamId)
        {
            /*
             * 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).
             */

            IAudioSamples samples = IAudioSamples.make(512, audioCoder.getChannels(),IAudioSamples.Format.FMT_S16 );

            /*
             * 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 < packet.getSize())
            {
                int bytesDecoded = audioCoder.decodeAudio(samples, packet, offset);
                if (bytesDecoded < 0)
                    throw new RuntimeException("got error decoding audio in: " + filename);

                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(streamIndex, samples);   
                }
            }
        }
        else
        {
            /*
             * This packet isn't part of our audio stream, so we just silently drop it.
             */
            do {} while(false);
        }
    }

I'm trying to convert aac/wav/wma audio files to mp3 with Xuggler in Java.

Unfortunately, I have a big loss of quality. My input file size is about 7MB and my output file size is only 1,5MB.

The sample rate is set to 44100 Hz, is there other parameters to set?

Thank you for your answers.

  if (args.length <= 1)
        throw new IllegalArgumentException("must pass an input filename and output filename as argument");

    IMediaWriter writer = ToolFactory.makeWriter(args[1]);

    String filename = args[0];

    // Create a Xuggler container object
    IContainer container = IContainer.make();

    // Open up the container
    if (container.open(filename, IContainer.Type.READ, null) < 0)
        throw new IllegalArgumentException("could not open file: " + filename);

    // query how many streams the call to open found
    int numStreams = container.getNumStreams();

    // and iterate through the streams to find the first audio stream
    int audioStreamId = -1;
    IStreamCoder audioCoder = null;
    for(int i = 0; i < numStreams; i++)
    {
        // Find the stream object
        IStream stream = container.getStream(i);
        // Get the pre-configured decoder that can decode this stream;
        IStreamCoder coder = stream.getStreamCoder();

        if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO)
        {
            audioStreamId = i;
            audioCoder = coder;
            audioCoder.setBitRate(container.getBitRate());

            break;
        }
    }

    if (audioStreamId == -1)
        throw new RuntimeException("could not find audio stream in container: "+filename);

    /* We read only AAC file for the moment */
    if(audioCoder.getCodecID() != ICodec.ID.CODEC_ID_AAC 
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WAVPACK 
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WMAV1
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WMAV2
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WMAPRO
        && audioCoder.getCodecID() != ICodec.ID.CODEC_ID_WMAVOICE)
    {
        System.out.println("Read only AAC, WAV or WMA files");
        System.exit(1);
    }

    audioCoder.setSampleFormat(IAudioSamples.Format.FMT_S16);
    /*
     * Now we have found the audio stream in this file.  Let's open up our decoder so it can
     * do work.
     */
    if (audioCoder.open() < 0)
        throw new RuntimeException("could not open audio decoder for container: "+filename);

    int streamIndex = writer.addAudioStream(0, 0, audioCoder.getChannels(), audioCoder.getSampleRate());


    System.out.println("audio Frame size : "+audioCoder.getAudioFrameSize());


    /*
     * Now, we start walking through the container looking at each packet.
     */
    IPacket packet = IPacket.make();

    while(container.readNextPacket(packet) >= 0)
    {
        /*
         * Now we have a packet, let's see if it belongs to our audio stream
         */
        if (packet.getStreamIndex() == audioStreamId)
        {
            /*
             * 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).
             */

            IAudioSamples samples = IAudioSamples.make(512, audioCoder.getChannels(),IAudioSamples.Format.FMT_S16 );

            /*
             * 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 < packet.getSize())
            {
                int bytesDecoded = audioCoder.decodeAudio(samples, packet, offset);
                if (bytesDecoded < 0)
                    throw new RuntimeException("got error decoding audio in: " + filename);

                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(streamIndex, samples);   
                }
            }
        }
        else
        {
            /*
             * This packet isn't part of our audio stream, so we just silently drop it.
             */
            do {} while(false);
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

池木 2024-12-04 10:46:59

我会做这样的事情:

public void convertToMP3(File input, File output, int kbps) { //modify on your convenience
    // create a media reader
    IMediaReader mediaReader = ToolFactory.makeReader(input.getPath());

    // create a media writer
    IMediaWriter mediaWriter = ToolFactory.makeWriter(output.getPath(), mediaReader);

    // add a writer to the reader, to create the output file
    mediaReader.addListener(mediaWriter);

    // add a IMediaListner to the writer to change bit rate
    mediaWriter.addListener(new MediaListenerAdapter() {
        @Override
        public void onAddStream(IAddStreamEvent event) {
            IStreamCoder streamCoder = event.getSource().getContainer().getStream(event.getStreamIndex()).getStreamCoder();
            streamCoder.setFlag(IStreamCoder.Flags.FLAG_QSCALE, false);
            streamCoder.setBitRate(kbps);
            streamCoder.setBitRateTolerance(0);
            }
        });

    // read and decode packets from the source file and
    // and dispatch decoded audio and video to the writer
    while (mediaReader.readPacket() == null);
}

输入是你想要转换的文件(aac/wav/wma),输出是一个新的.mp3文件(Xuggler通过扩展名计算出转换)。

您可以通过增加 kbps 来提高质量(即,对于 320 kbps,您需要传递 320000)。

希望有所帮助:-)

仅供参考:对于 Java 项目,如果您尚未导入以下内容,则需要导入以下内容:

import com.xuggle.mediatool.MediaListenerAdapter;
import com.xuggle.mediatool.event.IAddStreamEvent;
import com.xuggle.xuggler.IStreamCoder;

I'll do something like this:

public void convertToMP3(File input, File output, int kbps) { //modify on your convenience
    // create a media reader
    IMediaReader mediaReader = ToolFactory.makeReader(input.getPath());

    // create a media writer
    IMediaWriter mediaWriter = ToolFactory.makeWriter(output.getPath(), mediaReader);

    // add a writer to the reader, to create the output file
    mediaReader.addListener(mediaWriter);

    // add a IMediaListner to the writer to change bit rate
    mediaWriter.addListener(new MediaListenerAdapter() {
        @Override
        public void onAddStream(IAddStreamEvent event) {
            IStreamCoder streamCoder = event.getSource().getContainer().getStream(event.getStreamIndex()).getStreamCoder();
            streamCoder.setFlag(IStreamCoder.Flags.FLAG_QSCALE, false);
            streamCoder.setBitRate(kbps);
            streamCoder.setBitRateTolerance(0);
            }
        });

    // read and decode packets from the source file and
    // and dispatch decoded audio and video to the writer
    while (mediaReader.readPacket() == null);
}

input is the File (aac/wav/wma) you want to convert and output is a new .mp3 file (Xuggler figure out the conversion by the extension).

You can increase the quality increasing kbps (i.e. for 320 kbps you need to pass in 320000).

Hope that helps :-)

FYI: for Java projects you'll need to import the following if you haven't already done so:

import com.xuggle.mediatool.MediaListenerAdapter;
import com.xuggle.mediatool.event.IAddStreamEvent;
import com.xuggle.xuggler.IStreamCoder;
请帮我爱他 2024-12-04 10:46:59

我不确定确切的选项及其作用,但请查看 IStreamCoder 的 javadoc。您可能还想尝试其他各种选项。如果您想要完全控制,您甚至可以使用 setFlags() 方法直接在 ffmpeg 上设置标志(Xuggler 在下面使用)。

I'm not sure of the exact options and what they do, but take a look at the javadoc for IStreamCoder. There's various other options there you might want to play with. You can even set flags on ffmpeg directly (which Xuggler uses underneath) with the setFlags() method if you want complete control.

ぺ禁宫浮华殁 2024-12-04 10:46:59

当你有一个带有封面(png)的mp3时要小心,你可能会遇到错误,因为你试图将视频png流发送到音频流。通过使用ISamples并使用if(packet.getStreamIndex()==audioStreamId)读取数据包{} 可以更好地控制您使用的流。
检查我的完整代码:

private static void streamToSource( OutputStream source, Path path ) throws IOException {

    byte[] buffer = new byte[4096];
    PipedInputStream pis = new PipedInputStream( );
    PipedOutputStream pos = new PipedOutputStream( pis );
    convertToMP3Xuggler( path, pos );

    System.out.println( "start streaming" );
    int nRead = 0;
    while ( ( nRead = pis.read( buffer ) ) != -1 ) {
        source.write( buffer,0 , nRead );
    }
    pis.close( );

    System.out.println( "end : " + path );

}

private static void convertToMP3Xuggler( Path path, PipedOutputStream pos ) throws FileNotFoundException {

    // create a media reader
    // final IMediaReader mediaReader = ToolFactory.makeReader( XugglerIO.map( new FileInputStream( path.toFile( ) ) ) );

    // create a media writer
    // IMediaWriter mediaWriter = ToolFactory.makeWriter( XugglerIO.map( XugglerIO.generateUniqueName( os, ".mp3" ), os ), mediaReader );
    IMediaWriter mediaWriter = ToolFactory.makeWriter( XugglerIO.map( pos ) );
    // manually set the container format (because it can't detect it by filename anymore)


    IContainerFormat containerFormat = IContainerFormat.make( );
    containerFormat.setOutputFormat( "mp3", null, "audio/mp3" );
    mediaWriter.getContainer( ).setFormat( containerFormat );

    System.out.println( "file = " + path.toFile( ).toString( ) );

    IContainer audioContainer = IContainer.make( );
    audioContainer.open( path.toFile( ).toString( ), IContainer.Type.READ, null );

    System.out.println( "streams= " + audioContainer.getNumStreams( ) );
    System.out.println( "# Duration (ms): " + ( ( audioContainer.getDuration( ) == Global.NO_PTS ) ? "unknown" : "" + audioContainer.getDuration( ) / 1000 ) );
    System.out.println( "# File size (bytes): " + audioContainer.getFileSize( ) );
    System.out.println( "# Bit rate: " + audioContainer.getBitRate( ) );
    int audioStreamId = -1;


    for ( int i = 0; i < audioContainer.getNumStreams( ); i++ ) {
        // Find the stream object
        IStream stream = audioContainer.getStream( i );
        // Get the pre-configured decoder that can decode this stream;
        IStreamCoder coder = stream.getStreamCoder( );
        if ( coder.getCodecType( ) == ICodec.Type.CODEC_TYPE_AUDIO ) {
            audioStreamId = i;
            break;
        }
    }
    if ( audioStreamId < 0 ) {
        throw new IllegalArgumentException( "cannot find audio stream in the current file : " + path.toString( ) );
    }
    System.out.println( "found audio stream = " + audioStreamId );

    IStreamCoder coderAudio = audioContainer.getStream( audioStreamId ).getStreamCoder( );

    if ( coderAudio.open( null, null ) < 0 ) {
        throw new RuntimeException( "Cant open audio coder" );
    }
    coderAudio.setSampleFormat( IAudioSamples.Format.FMT_S16 );

    System.out.println( "bitrate from reading = " + audioContainer.getBitRate( ) );
    System.out.println( "bitrate from reading = " + coderAudio.getBitRate( ) );

    int streamIndex = mediaWriter.addAudioStream( 0, 0, coderAudio.getChannels( ), coderAudio.getSampleRate( ) );
    IStreamCoder writerCoder = mediaWriter.getContainer( ).getStream( streamIndex ).getStreamCoder( );
    writerCoder.setFlag( IStreamCoder.Flags.FLAG_QSCALE, false );
    writerCoder.setBitRate( BITRATE * 1000 );
    writerCoder.setBitRateTolerance( 0 );
    System.out.println( "bitrate for output = " + writerCoder.getBitRate( ) );

    IPacket packet = IPacket.make( );

    runInThread( path, pos, mediaWriter, audioContainer, audioStreamId, coderAudio, streamIndex, packet );

}

private static void runInThread( Path path, PipedOutputStream pos, IMediaWriter mediaWriter, IContainer audioContainer, int audioStreamId, IStreamCoder coderAudio, int streamIndex, IPacket packet ) {

    new Thread( ) {
        @Override
        public void run( ) {

            while ( audioContainer.readNextPacket( packet ) >= 0 ) {
                /*
                 * Now we have a packet, let's see if it belongs to our audio stream
                 */
                if ( packet.getStreamIndex( ) == audioStreamId ) {
                    /*
                     * 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 (4096 in our example), although Xuggler
                     * will probably allocate more space than just the 4096 (it's not important why).
                     */

                    IAudioSamples samples = IAudioSamples.make( 4096, coderAudio.getChannels( ), IAudioSamples.Format.FMT_S16 );

                    /*
                     * 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 < packet.getSize( ) ) {
                        int bytesDecoded = coderAudio.decodeAudio( samples, packet, offset );
                        if ( bytesDecoded < 0 ) {
                            System.out.println( "decode error in : " + path + " bytesDecoded =" + bytesDecoded + " offset=" + offset + " packet=" + packet );
                            break;
                            //                                throw new RuntimeException( "got error decoding audio in: " + path );
                        }

                        offset += bytesDecoded;

                        //                            System.out.println( "pktSize = " + packet.getSize( ) + "  offset = " + offset + " samplesComplete = " + samples.isComplete( ) );

                        /*
                         * 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( ) ) {
                            mediaWriter.encodeAudio( streamIndex, samples );
                        }
                    }
                }
            }
            coderAudio.close( );
            audioContainer.close( );
            mediaWriter.close( );
            try {
                pos.close( );
            } catch ( IOException e ) {
                e.printStackTrace( );
            }
        }

    }.start( );
}

Be carefull when you have a mp3 with cover (png) you could end up with errors because you are trying to send video png stream to audio stream.. By using ISamples and reading packet with if ( packet.getStreamIndex( ) == audioStreamId ) {} gives a better control over the stream that you use.
check my full code:

private static void streamToSource( OutputStream source, Path path ) throws IOException {

    byte[] buffer = new byte[4096];
    PipedInputStream pis = new PipedInputStream( );
    PipedOutputStream pos = new PipedOutputStream( pis );
    convertToMP3Xuggler( path, pos );

    System.out.println( "start streaming" );
    int nRead = 0;
    while ( ( nRead = pis.read( buffer ) ) != -1 ) {
        source.write( buffer,0 , nRead );
    }
    pis.close( );

    System.out.println( "end : " + path );

}

private static void convertToMP3Xuggler( Path path, PipedOutputStream pos ) throws FileNotFoundException {

    // create a media reader
    // final IMediaReader mediaReader = ToolFactory.makeReader( XugglerIO.map( new FileInputStream( path.toFile( ) ) ) );

    // create a media writer
    // IMediaWriter mediaWriter = ToolFactory.makeWriter( XugglerIO.map( XugglerIO.generateUniqueName( os, ".mp3" ), os ), mediaReader );
    IMediaWriter mediaWriter = ToolFactory.makeWriter( XugglerIO.map( pos ) );
    // manually set the container format (because it can't detect it by filename anymore)


    IContainerFormat containerFormat = IContainerFormat.make( );
    containerFormat.setOutputFormat( "mp3", null, "audio/mp3" );
    mediaWriter.getContainer( ).setFormat( containerFormat );

    System.out.println( "file = " + path.toFile( ).toString( ) );

    IContainer audioContainer = IContainer.make( );
    audioContainer.open( path.toFile( ).toString( ), IContainer.Type.READ, null );

    System.out.println( "streams= " + audioContainer.getNumStreams( ) );
    System.out.println( "# Duration (ms): " + ( ( audioContainer.getDuration( ) == Global.NO_PTS ) ? "unknown" : "" + audioContainer.getDuration( ) / 1000 ) );
    System.out.println( "# File size (bytes): " + audioContainer.getFileSize( ) );
    System.out.println( "# Bit rate: " + audioContainer.getBitRate( ) );
    int audioStreamId = -1;


    for ( int i = 0; i < audioContainer.getNumStreams( ); i++ ) {
        // Find the stream object
        IStream stream = audioContainer.getStream( i );
        // Get the pre-configured decoder that can decode this stream;
        IStreamCoder coder = stream.getStreamCoder( );
        if ( coder.getCodecType( ) == ICodec.Type.CODEC_TYPE_AUDIO ) {
            audioStreamId = i;
            break;
        }
    }
    if ( audioStreamId < 0 ) {
        throw new IllegalArgumentException( "cannot find audio stream in the current file : " + path.toString( ) );
    }
    System.out.println( "found audio stream = " + audioStreamId );

    IStreamCoder coderAudio = audioContainer.getStream( audioStreamId ).getStreamCoder( );

    if ( coderAudio.open( null, null ) < 0 ) {
        throw new RuntimeException( "Cant open audio coder" );
    }
    coderAudio.setSampleFormat( IAudioSamples.Format.FMT_S16 );

    System.out.println( "bitrate from reading = " + audioContainer.getBitRate( ) );
    System.out.println( "bitrate from reading = " + coderAudio.getBitRate( ) );

    int streamIndex = mediaWriter.addAudioStream( 0, 0, coderAudio.getChannels( ), coderAudio.getSampleRate( ) );
    IStreamCoder writerCoder = mediaWriter.getContainer( ).getStream( streamIndex ).getStreamCoder( );
    writerCoder.setFlag( IStreamCoder.Flags.FLAG_QSCALE, false );
    writerCoder.setBitRate( BITRATE * 1000 );
    writerCoder.setBitRateTolerance( 0 );
    System.out.println( "bitrate for output = " + writerCoder.getBitRate( ) );

    IPacket packet = IPacket.make( );

    runInThread( path, pos, mediaWriter, audioContainer, audioStreamId, coderAudio, streamIndex, packet );

}

private static void runInThread( Path path, PipedOutputStream pos, IMediaWriter mediaWriter, IContainer audioContainer, int audioStreamId, IStreamCoder coderAudio, int streamIndex, IPacket packet ) {

    new Thread( ) {
        @Override
        public void run( ) {

            while ( audioContainer.readNextPacket( packet ) >= 0 ) {
                /*
                 * Now we have a packet, let's see if it belongs to our audio stream
                 */
                if ( packet.getStreamIndex( ) == audioStreamId ) {
                    /*
                     * 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 (4096 in our example), although Xuggler
                     * will probably allocate more space than just the 4096 (it's not important why).
                     */

                    IAudioSamples samples = IAudioSamples.make( 4096, coderAudio.getChannels( ), IAudioSamples.Format.FMT_S16 );

                    /*
                     * 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 < packet.getSize( ) ) {
                        int bytesDecoded = coderAudio.decodeAudio( samples, packet, offset );
                        if ( bytesDecoded < 0 ) {
                            System.out.println( "decode error in : " + path + " bytesDecoded =" + bytesDecoded + " offset=" + offset + " packet=" + packet );
                            break;
                            //                                throw new RuntimeException( "got error decoding audio in: " + path );
                        }

                        offset += bytesDecoded;

                        //                            System.out.println( "pktSize = " + packet.getSize( ) + "  offset = " + offset + " samplesComplete = " + samples.isComplete( ) );

                        /*
                         * 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( ) ) {
                            mediaWriter.encodeAudio( streamIndex, samples );
                        }
                    }
                }
            }
            coderAudio.close( );
            audioContainer.close( );
            mediaWriter.close( );
            try {
                pos.close( );
            } catch ( IOException e ) {
                e.printStackTrace( );
            }
        }

    }.start( );
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文