音频与Xuggler转换 [英] Audio converting with Xuggler

查看:1019
本文介绍了音频与Xuggler转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图AAC / WAV / WMA音频文件转换成MP3与Xuggler在Java中。

不幸的是,我有质量的一大损失。我输入文件大小约为7MB和我的输出文件大小只有1,5MB。

采样率设置为44100赫兹,有没有其他的参数设置?

感谢您的答案。

 如果(args.length< = 1)
        抛出新抛出:IllegalArgumentException(必须通过输入文件名和输出文件名作为参数);    IMediaWriter作家= ToolFactory.makeWriter(参数[1]);    字符串文件名= ARGS [0];    //创建一个Xuggler容器对象
    集装箱的IContainer = IContainer.make();    //打开容器
    如果(container.open(文件名,IContainer.Type.READ,零)℃的)
        抛出新抛出:IllegalArgumentException(无法打开文件:+文件名);    //查询有多少流的调用打开发现
    INT numStreams = container.getNumStreams();    //并遍历流找到第一个音频流
    INT audioStreamId = -1;
    的IStream codeR音频codeR = NULL;
    的for(int i = 0; I< numStreams;我++)
    {
        //查找流对象
        的IStream流= container.getStream(I)
        //获取pre-配置德codeR可以去code此流;
        的IStream codeR codeR = stream.getStream codeR();        如果(coder.get codecType()== I codec.Type。codeC_TYPE_AUDIO)
        {
            audioStreamId = I;
            音频codeR = codeR;
            音频coder.setBitRate(container.getBitRate());            打破;
        }
    }    如果(audioStreamId == -1)
        抛出新的RuntimeException(集装箱找不到音频流:+文件名);    / *我们只读AAC文件中暂时* /
    如果(音频coder.get codeCID()!= I codec.ID. codeC_ID_AAC
        &功放;&安培;音频coder.get codeCID()!= I codec.ID. codeC_ID_WAVPACK
        &功放;&安培;音频coder.get codeCID()!= I codec.ID. codeC_ID_WMAV1
        &功放;&安培;音频coder.get codeCID()!= I codec.ID. codeC_ID_WMAV2
        &功放;&安培;音频coder.get codeCID()!= I codec.ID. codeC_ID_WMAPRO
        &功放;&安培;音频coder.get codeCID()!= I codec.ID. codeC_ID_WMAVOICE)
    {
        的System.out.println(只读AAC,WAV或WMA文件);
        System.exit(1);
    }    音频coder.setSampleFormat(IAudioSamples.Format.FMT_S16);
    / *
     *现在我们已发现在该文件中的音频流。让我们打开了我们去codeR因此它可以
     * 做工作。
     * /
    如果(音频coder.open()℃,)
        抛出新的RuntimeException(无法打开音频解codeR集装箱:+文件名);    INT streamIndex = writer.addAudioStream(0,0,音频coder.getChannels(),音频coder.getSampleRate());
    的System.out.println(音频帧的大小:+音频coder.getAudioFrameSize());
    / *
     *现在,我们开始通过容器看着每一个数据包走。
     * /
    IPacket包= IPacket.make();    而(container.readNextPacket(分组)GT; = 0)
    {
        / *
         *现在我们有一个包,让我们来看看它是否属于我们的音频流
         * /
        如果(packet.getStreamIndex()== audioStreamId)
        {
            / *
             *我们分配一组样品的具有相同数目的信道作为的
             * codeR告诉我们在这个缓冲区。
             *
             *我们还传递一个缓冲区大小(1024在我们的例子),虽然Xuggler
             *可能会分配不仅仅是1024更多的空间(这并不重要原因)。
             * /            IAudioSamples样品= IAudioSamples.make(512,音频coder.getChannels(),IAudioSamples.Format.FMT_S16);            / *
             *数据包实际上可以包含样本的多组(或样本帧
             *音频解码说吧)。因此,我们可能需要去code音频多打电话
             *在该分组的数据不同的偏移时间。我们捕获在这里。
             * /
            INT偏移= 0;            / *
             *保持下去,直到我们处理完所有数据
             * /            而(偏移下; packet.getSize())
            {
                INT bytesDe codeD =音频coder.de codeAudio(样本,数据包,偏移量);
                如果(bytesDe codeD℃下)
                    抛出新的RuntimeException(中得到了错误解码音频:+文件名);                胶印+ = bytesDe codeD;                / *
                 *一些德codeR将在分组消耗的数据,但将不能够构造
                 *全套样品呢。因此,你应该经常检查,如果你
                 *得到了来自德codeR样品的一套完整
                 * /
                如果(samples.isComplete())
                {
                    writer.en codeAudio(streamIndex,样本);
                }
            }
        }
        其他
        {
            / *
             *这个包是不是我们的音频流的一部分,所以我们只是默默的放弃它。
             * /
            做{}而(假);
        }
    }


解决方案

我会做这样的事情:

 公共无效convertToMP3(文件输入,文件输出,诠释kbps的){//您的方便修改
    //创建一个读卡器
    IMediaReader mediaReader = ToolFactory.makeReader(input.getPath());    //创建一个媒体记录器
    IMediaWriter mediaWriter = ToolFactory.makeWriter(output.getPath(),mediaReader);    //一个作家加入到阅读器,创建输出文件
    mediaReader.addListener(mediaWriter);    //一个IMediaListner添加到作家改变比特率
    mediaWriter.addListener(新MediaListenerAdapter(){
        @覆盖
        公共无效onAddStream(IAddStreamEvent事件){
            的IStream codeR流codeR = event.getSource()getContainer()getStream(event.getStreamIndex())getStream codeR()。;
            流coder.setFlag(的IStream coder.Flags.FLAG_QSCALE,FALSE);
            流coder.setBitRate(Kbps)的;
            流coder.setBitRateTolerance(0);
            }
        });    //读取并从源文件去code包,
    //调度德codeD音频和视频的作家
    而(mediaReader.readPacket()== NULL);
}

输入要转换和输出是一个新的.MP3文件(Xuggler弄清楚转换的扩展名)。文件(AAC / WAV / WMA)

您可以提高质量增加kbps的(即你需要320000传递到320 kbps)。

希望有所帮助: - )

FYI:对于Java项目,您需要导入以下,如果你还没有这样做的:

 进口com.xuggle.mediatool.MediaListenerAdapter;
进口com.xuggle.mediatool.event.IAddStreamEvent;
进口com.xuggle.xuggler.IStream codeR;

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);
        }
    }

解决方案

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;

这篇关于音频与Xuggler转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆