【问题标题】:JAVA - Xuggler - combine an MP3 audio file and a MP4 movieJAVA - Xuggler - 结合 MP3 音频文件和 MP4 电影
【发布时间】:2013-11-06 12:45:03
【问题描述】:

使用 JAVA 和 Xuggler - 下面的代码组合了一个 MP3 音频文件和一个 MP4 电影文件并输出一个组合的 mp4 文件。

我希望输出视频的时长等于输入视频文件的时长

如果我将循环条件设置为:

while (containerVideo.readNextPacket(packetvideo) >= 0) 

它提供 400 次迭代 - 使影片运行 15 秒。正是我想要的。

但由于某种原因,音频在 10 秒后被切断 - 使电影的最后 5 秒无声。

看起来好像视频 IStreamCoder 的单次迭代的持续时间与音频 IStreamCoder 的单次迭代的持续时间不同。

如何让声音充满整部电影的 15 秒?

    String inputVideoFilePath = "in.mp4";
    String inputAudioFilePath = "in.mp3";
    String outputVideoFilePath = "out.mp4";

    IMediaWriter mWriter = ToolFactory.makeWriter(outputVideoFilePath);

    IContainer containerVideo = IContainer.make();
    IContainer containerAudio = IContainer.make();

    // check files are readable
    if (containerVideo.open(inputVideoFilePath, IContainer.Type.READ, null) < 0)
        throw new IllegalArgumentException("Cant find " + inputVideoFilePath);
    if (containerAudio.open(inputAudioFilePath, IContainer.Type.READ, null) < 0)
        throw new IllegalArgumentException("Cant find " + inputAudioFilePath);

    // read video file and create stream
    IStreamCoder coderVideo = containerVideo.getStream(0).getStreamCoder();
    if (coderVideo.open(null, null) < 0)
        throw new RuntimeException("Cant open video coder");
    IPacket packetvideo = IPacket.make();
    int width = coderVideo.getWidth();
    int height = coderVideo.getHeight();

    // read audio file and create stream
    IStreamCoder coderAudio = containerAudio.getStream(0).getStreamCoder();
    if (coderAudio.open(null, null) < 0)
        throw new RuntimeException("Cant open audio coder");
    IPacket packetaudio = IPacket.make();

    mWriter.addAudioStream(1, 0, coderAudio.getChannels(), coderAudio.getSampleRate());
    mWriter.addVideoStream(0, 0, width, height);

    while (containerVideo.readNextPacket(packetvideo) >= 0) {

        containerAudio.readNextPacket(packetaudio);

        // video packet
        IVideoPicture picture = IVideoPicture.make(coderVideo.getPixelType(), width, height);
        coderVideo.decodeVideo(picture, packetvideo, 0);
        if (picture.isComplete()) 
            mWriter.encodeVideo(0, picture);

        // audio packet 
        IAudioSamples samples = IAudioSamples.make(512, coderAudio.getChannels(), IAudioSamples.Format.FMT_S32);
        coderAudio.decodeAudio(samples, packetaudio, 0);
        if (samples.isComplete()) 
            mWriter.encodeAudio(1, samples);

    }

    coderAudio.close();
    coderVideo.close();
    containerAudio.close();
    containerVideo.close();
    mWriter.close();

【问题讨论】:

    标签: java mp3 mp4 xuggler


    【解决方案1】:

    不错的代码。谢谢。要捕获剩余的音频,请在末尾添加一个循环以读取音频数据包,直到不再有。

        while (samples.isComplete() ) {
            containerAudio.readNextPacket(packetaudio);
            coderAudio.decodeAudio(samples, packetaudio, 0);
            writer.encodeAudio(iAudioStream, samples);
            Utility.console(String.format("%s %d", Utility.timeStamp(),
                samples.getPts() ));            
        }
    

    【讨论】:

      【解决方案2】:

      我意识到这是旧的,但我遇到了它,它完全符合我的需要,但我遇到了同样的问题(我的音频过早停止了)。 Eli的回答有效,但做了一些调整。我在这里发布更改,希望能节省一些时间。 免责声明:我不太了解 Xuggle,我不知道这是否是最好的方法,但我知道它为我完成了工作:

          String inputVideoFilePath = "in.mp4";
          String inputAudioFilePath = "in.mp3";
          String outputVideoFilePath = "out.mp4";
      
          IMediaWriter mWriter = ToolFactory.makeWriter(outputVideoFilePath);
      
          IContainer containerVideo = IContainer.make();
          IContainer containerAudio = IContainer.make();
      
          // check files are readable
          if (containerVideo.open(inputVideoFilePath, IContainer.Type.READ, null) < 0)
              throw new IllegalArgumentException("Cant find " + inputVideoFilePath);
          if (containerAudio.open(inputAudioFilePath, IContainer.Type.READ, null) < 0)
              throw new IllegalArgumentException("Cant find " + inputAudioFilePath);
      
          // read video file and create stream
          IStreamCoder coderVideo = containerVideo.getStream(0).getStreamCoder();
          if (coderVideo.open(null, null) < 0)
              throw new RuntimeException("Cant open video coder");
          IPacket packetvideo = IPacket.make();
          int width = coderVideo.getWidth();
          int height = coderVideo.getHeight();
      
          // read audio file and create stream
          IStreamCoder coderAudio = containerAudio.getStream(0).getStreamCoder();
          if (coderAudio.open(null, null) < 0)
              throw new RuntimeException("Cant open audio coder");
          IPacket packetaudio = IPacket.make();
      
          mWriter.addAudioStream(1, 0, coderAudio.getChannels(), coderAudio.getSampleRate());
          mWriter.addVideoStream(0, 0, width, height);
      
          while (containerVideo.readNextPacket(packetvideo) >= 0) {
      
              containerAudio.readNextPacket(packetaudio);
      
              // video packet
              IVideoPicture picture = IVideoPicture.make(coderVideo.getPixelType(), width, height);
              coderVideo.decodeVideo(picture, packetvideo, 0);
              if (picture.isComplete()) 
                  mWriter.encodeVideo(0, picture);
      
              // audio packet 
              IAudioSamples samples = IAudioSamples.make(512, coderAudio.getChannels(), IAudioSamples.Format.FMT_S32);
              coderAudio.decodeAudio(samples, packetaudio, 0);
              if (samples.isComplete()) 
                  mWriter.encodeAudio(1, samples);
      
          }
      
      
      //<added_code> This is Eli Sokal's code tweaked to work with gilad s' code
      
          IAudioSamples samples;
          do {
              samples = IAudioSamples.make(512, coderAudio.getChannels(), IAudioSamples.Format.FMT_S32);
              containerAudio.readNextPacket(packetaudio);
              coderAudio.decodeAudio(samples, packetaudio, 0);
              mWriter.encodeAudio(1, samples);
          }while (samples.isComplete() );
      
      //</added_code>
      
      
          coderAudio.close();
          coderVideo.close();
          containerAudio.close();
          containerVideo.close();
          mWriter.close();
      

      【讨论】:

        猜你喜欢
        • 2014-07-10
        • 2022-01-09
        • 1970-01-01
        • 2016-06-26
        • 1970-01-01
        • 2016-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多