JAVA - Xuggler - 组合 MP3 音频文件和 MP4 电影时播放视频

标签 java mp3 mp4 video-player

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

我希望输出视频文件在合并音频和视频文件时自动播放。

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 xuggler合并音频和视频文件时自动播放视频文件..请帮助我..这将非常感激..

最佳答案

这是完整的代码。 我还做了一些修改:如果音频较长,则将其余部分分开写,并在标题栏中添加了音频和视频的进度。您可能需要检查文件中是否确实存在视频或音频流,以防止出现错误。

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) + "%");
    }
}

如果您需要根据视频帧速率显示帧,请在每次读取视频数据包后添加以下代码,否则将其保留以进行快速合并。

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

关于JAVA - Xuggler - 组合 MP3 音频文件和 MP4 电影时播放视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23784422/

相关文章:

java - 使用 MapStruct 将 2 个字符串字段映射到 OffsetDateTime

java - 记录通过套接字连接发送/接收的内容

ios - 如何在iphone应用程序中压缩音频文件

ios - 如何在登录屏幕上显示动画

iPhone MP4 视频播放列表

c++ - 如何用Media Foundation生成 "moov before mdat"MP4视频文件

java - 使用数组列表按升序和降序排列字符串

java - 两人网格遍历游戏

express - 为什么node-lame模块保存的mp3文件音调高/播放速度快?

linux - 从 LAME 和 FLAC 获取输出以显示在 bash 对话框中