JAVA - Xuggler - Play video while combining an MP3 audio file and a MP4 movie

两盒软妹~` 提交于 2019-12-11 01:13:15

问题


Using JAVA and Xuggler - the following code combines an MP3 audio file and a MP4 movie file and outputs a combined mp4 file.

I want outputVideo file should be play automatically while combining audio and video file.

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

If anybody knows play video file automatically when combining audio and video file using java xuggler.. please please help me..It would be really appreciable..


回答1:


Here is the complete code. I also did some changes: if audio is longer, then write the rest separately, and added progress of audio and video in title bar. You may need to check if there is really video or audio stream in your files to prevent errors.

import com.xuggle.mediatool.IMediaWriter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.xuggler.Global;
import com.xuggle.xuggler.IAudioSamples;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IStreamCoder;
import com.xuggle.xuggler.IVideoPicture;
import com.xuggle.xuggler.video.ConverterFactory;
import com.xuggle.xuggler.video.IConverter;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 *
 * @author Pasban
 */
public class MergeVideoAudio extends JDialog {

    Image image;
    private double video_duration = 0.00001, video_read = 0, audio_duration = 0.00001, audio_read = 0;

    public static void main(String[] args) {
        final MergeVideoAudio merge = new MergeVideoAudio();
        Thread thread = new Thread() {

            @Override
            public void run() {
                merge.perform("y:/a.mp4", "y:/b.mp3", "y:/c.mp4");
                merge.setVisible(false);
                System.exit(0);
            }
        };
        thread.run();
    }

    public void perform(String path_video, String path_audio, String path_output) {

        IMediaWriter mWriter = ToolFactory.makeWriter(path_output);
        IContainer containerVideo = IContainer.make();
        IContainer containerAudio = IContainer.make();

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

        if (containerAudio.open(path_audio, IContainer.Type.READ, null) < 0) {
            throw new IllegalArgumentException("Cant find " + path_audio);
        }

// 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");
        }
        int width = coderVideo.getWidth();
        int height = coderVideo.getHeight();

        this.setSize(width, height);
        this.setLocationRelativeTo(null);
        this.setVisible(true);

// 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 packet = IPacket.make();

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

        video_duration = 0.000001 + (containerVideo.getDuration() == Global.NO_PTS ? 0 : (containerVideo.getDuration() / 1000.0));
        audio_duration = 0.000001 + (containerAudio.getDuration() == Global.NO_PTS ? 0 : (containerAudio.getDuration() / 1000.0));

        while (containerVideo.readNextPacket(packet) >= 0) {
            video_read = (packet.getTimeStamp() * packet.getTimeBase().getDouble() * 1000);

// video packet
            IVideoPicture picture = IVideoPicture.make(coderVideo.getPixelType(), width, height);
            coderVideo.decodeVideo(picture, packet, 0);
            if (picture.isComplete()) {
                mWriter.encodeVideo(0, picture);
                IConverter converter = ConverterFactory.createConverter(ConverterFactory.XUGGLER_BGR_24, picture);
                this.setImage(converter.toImage(picture));
                this.setProgress(video_duration, video_read, audio_duration, audio_read);
            }

// audio packet 
            containerAudio.readNextPacket(packet);
            audio_read = (packet.getTimeStamp() * packet.getTimeBase().getDouble() * 1000);
            IAudioSamples samples = IAudioSamples.make(512, coderAudio.getChannels(), IAudioSamples.Format.FMT_S32);
            coderAudio.decodeAudio(samples, packet, 0);
            if (samples.isComplete()) {
                mWriter.encodeAudio(1, samples);
                this.setProgress(video_duration, video_read, audio_duration, audio_read);
            }

        }

//write the remaining audio, if your audio is longer than your video
        while (containerAudio.readNextPacket(packet) >= 0) {
            audio_read = (packet.getTimeStamp() * packet.getTimeBase().getDouble() * 1000);
            IAudioSamples samples = IAudioSamples.make(512, coderAudio.getChannels(), IAudioSamples.Format.FMT_S32);
            coderAudio.decodeAudio(samples, packet, 0);
            if (samples.isComplete()) {
                mWriter.encodeAudio(1, samples);
                this.setProgress(video_duration, video_read, audio_duration, audio_read);
            }
        }

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

        mWriter.close();
    }

    public MergeVideoAudio() {
        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    }

    public void setImage(final Image image) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                MergeVideoAudio.this.image = image;
                repaint();
            }
        });
    }

    @Override
    public synchronized void paint(Graphics g) {
        if (image != null) {
            g.drawImage(image, 0, 0, null);
        }
    }

    public static String convertDurationHMSm(double time) {
        long elapsed = (long) (time * 1000);
        long duration = elapsed / 1000;
        long ms = elapsed % 1000;
        return String.format("%02d:%02d:%02d.%02d", duration / 3600, (duration % 3600) / 60, (duration % 60), ms / 10);
    }

    private void setProgress(double video_duration, double video_read, double audio_duration, double audio_read) {
        this.setTitle("Video: " + (int) (100 * video_read / video_duration) + "%, Audio " + (int) (100 * audio_read / audio_duration) + "%");
    }
}

If you need to show frames based on video frame rate, then add the following code after every time you read your video packet, or else leave it for fast merging.

try {
    Thread.sleep((long) (1000 / coderVideo.getFrameRate().getDouble()));
} catch (InterruptedException ex) {
    ex.printStackTrace();
}



回答2:


It might be old, but all you need to do is to paint your picture on a jpanel. Something like this:

//Instead of 
if (picture.isComplete()){ 
    mWriter.encodeVideo(0, picture);
}

//Use
if (picture.isComplete()) {
    mWriter.encodeVideo(0, picture);
    IConverter converter = ConverterFactory.createConverter(ConverterFactory.XUGGLER_BGR_24, picture);
    repaint_on_jpanel_thread(converter.toImage(picture));
    //this is a function to paint the buffered image on your jpanel
}


来源:https://stackoverflow.com/questions/23784422/java-xuggler-play-video-while-combining-an-mp3-audio-file-and-a-mp4-movie

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!