0

我想使用 Xuggler将(flv)没有音频的视频文件与音频文件结合起来。(mp3)目前我已经拍摄了两个流,并将这些流的视频和音频部分分别组合在一起,就像画中画一样。现在我想将音频和视频文件相互结合。任何建议或提示将不胜感激。我正在使用red5服务器。谢谢。

4

3 回答 3

4

我开发了一个类,它将接受两个输入,一个音频文件和第二个视频文件,并将它们合并为一个音频视频文件。

 public static void main(String[] args)
  {

    String filenamevideo = "f:/testvidfol/video.mp4"; //video file on your disk
    String filenameaudio = "f:/testvidfol/audio.wav"; //audio file on your disk


    IMediaWriter mWriter = ToolFactory.makeWriter("f:/testvidfol/videowriter.flv"); //output file

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

    if (containerVideo.open(filenamevideo, IContainer.Type.READ, null) < 0)
        throw new IllegalArgumentException("Cant find " + filenamevideo);

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

    int numStreamVideo = containerVideo.getNumStreams();
    int numStreamAudio = containerAudio.getNumStreams();

    System.out.println("Number of video streams: "+numStreamVideo + "\n" + "Number of audio streams: "+numStreamAudio );

int videostreamt = -1; //this is the video stream id
int audiostreamt = -1;

IStreamCoder  videocoder = null;

    for(int i=0; i<numStreamVideo; i++){
        IStream stream = containerVideo.getStream(i);
        IStreamCoder code = stream.getStreamCoder();

        if(code.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO)
        {
            videostreamt = i;
            videocoder = code;
            break;
        }

    }

    for(int i=0; i<numStreamAudio; i++){
        IStream stream = containerAudio.getStream(i);
        IStreamCoder code = stream.getStreamCoder();

        if(code.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO)
        {
            audiostreamt = i;
            break;
        }

    }

    if (videostreamt == -1) throw new RuntimeException("No video steam found");
    if (audiostreamt == -1) throw new RuntimeException("No audio steam found");

    if(videocoder.open()<0 ) throw new RuntimeException("Cant open video coder");
    IPacket packetvideo = IPacket.make();

    IStreamCoder audioCoder = containerAudio.getStream(audiostreamt).getStreamCoder();

    if(audioCoder.open()<0 ) throw new RuntimeException("Cant open audio coder");
    mWriter.addAudioStream(0, 0, audioCoder.getChannels(), audioCoder.getSampleRate());

    mWriter.addVideoStream(1, 1, videocoder.getWidth(), videocoder.getHeight());

    IPacket packetaudio = IPacket.make();

    while(containerVideo.readNextPacket(packetvideo) >= 0 ||
            containerAudio.readNextPacket(packetaudio) >= 0){

        if(packetvideo.getStreamIndex() == videostreamt){

            //video packet
            IVideoPicture picture = IVideoPicture.make(videocoder.getPixelType(),
                    videocoder.getWidth(),
                    videocoder.getHeight());
            int offset = 0;
            while (offset < packetvideo.getSize()){
                int bytesDecoded = videocoder.decodeVideo(picture, 
                        packetvideo, 
                        offset);
                if(bytesDecoded < 0) throw new RuntimeException("bytesDecoded not working");
                offset += bytesDecoded;

                if(picture.isComplete()){
                    System.out.println(picture.getPixelType());
                    mWriter.encodeVideo(1, picture);

                }
            }
        } 

        if(packetaudio.getStreamIndex() == audiostreamt){   
        //audio packet

            IAudioSamples samples = IAudioSamples.make(512, 
                    audioCoder.getChannels(),
                    IAudioSamples.Format.FMT_S32);  
            int offset = 0;
            while(offset<packetaudio.getSize())
            {
                int bytesDecodedaudio = audioCoder.decodeAudio(samples, 
                        packetaudio,
                        offset);
                if (bytesDecodedaudio < 0)
                    throw new RuntimeException("could not detect audio");
                offset += bytesDecodedaudio;

                if (samples.isComplete()){
                     mWriter.encodeAudio(0, samples);

        }
            }

    }

  }
}

希望它会帮助你。

于 2012-08-07T09:53:07.317 回答
1

我知道这个线程很老,但提供的解决方案对我不起作用,我想我会在这里分享我的解决方案......

我将以下依赖项添加到我的 pom.xml

<!-- https://mvnrepository.com/artifact/org.bytedeco/ffmpeg -->
   <dependency>
       <groupId>org.bytedeco</groupId>
       <artifactId>ffmpeg</artifactId>
       <version>RELEASE</version>
   </dependency>

   <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
   <dependency>
       <groupId>org.bytedeco</groupId>
       <artifactId>javacv-platform</artifactId>
       <version>RELEASE</version>
   </dependency>

   <!-- https://mvnrepository.com/artifact/org.bytedeco/javacpp -->
   <dependency>
       <groupId>org.bytedeco</groupId>
       <artifactId>javacpp</artifactId>
       <version>RELEASE</version>
   </dependency>

然后我使用 ProcessBuilder 来执行 FFMPEG 命令。要合并音频和视频,我使用以下命令:

String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);
    try {
        ProcessBuilder pb = new ProcessBuilder(
                ffmpeg,
                "-i",
                [PATH TO AUDIO FILE],
                "-i",
                [PATH TO VIDEO FILE],
                "-acodec",
                "copy",
                "-vcodec",
                "copy",
                [PATH TO OUTPUT FILE]
        );
        
        pb.redirectErrorStream(true);
        Process process = pb.start();
        process.waitFor();

    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    } 
于 2020-11-13T19:30:38.293 回答
0

使用 MediaConcatenator。请参阅示例代码“连接音频和视频”

于 2012-01-17T08:08:24.393 回答