2

JAVA と Xuggler の使用 - 次のコードは、MP3 オーディオ ファイルと MP4 ムービー ファイルを結合し、結合された mp4 ファイルを出力します。

出力ビデオの長さを入力ビデオ ファイルの時間の長さと等しくしたい

ループ条件を次のように設定した場合:

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

400 回の反復が行われ、ムービーが 15 秒間実行されます。まさに私が望むように。

しかし、何らかの理由で音声が 10 秒後にカットされ、映画の最後の 5 秒間が無音になります。

ビデオ IStreamCoder の 1 回の反復の持続時間は、オーディオ IStreamCoder の 1 回の反復の持続時間とは異なるように見えます。

ムービーの 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();
4

2 に答える 2

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() ));            
    }
于 2013-11-25T02:08:52.560 に答える
0

私はこれが古いことに気付きましたが、私はそれに出くわし、まさに私が必要としていたことをしましたが、同じ問題がありました (オーディオが途中で停止しました)。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();
于 2016-01-08T06:25:39.750 に答える