使用JAVA和Xuggler - 以下代码组合了MP3音频文件和MP4电影文件,并输出了一个组合的mp4文件。
我希望outputVideo文件在播放音频和视频文件时自动播放。
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组合音频和视频文件时自动播放视频文件..请帮助我..这真的很明显..
答案 0 :(得分:2)
这是完整的代码。 我也做了一些更改:如果音频更长,则分别编写其余部分,并在标题栏中添加音频和视频的进度。您可能需要检查文件中是否存在真正的视频或音频流,以防止出错。
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();
}
答案 1 :(得分:1)
它可能很旧,但您需要做的就是在jpanel上绘制您的照片。像这样:
//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
}