如何使用Android MediaMuxer混合不同长度的音频和视频

时间:2018-07-26 12:10:47

标签: android media mediamuxer

我想使用android mediamuxer混合视频(1分钟)和音频(10秒)。我希望音频重复播放直到视频结束。当我使用下面的代码时,音频仅播放10秒钟。有人知道如何解决这个问题吗?

 mediaMuxer.start();
        while ((sampleSize = videoExtra.readSampleData(videoBuffer, 0 )) != -1) {
            videoBufferInfo.offset = 0;
            videoBufferInfo.size = sampleSize;
            videoBufferInfo.presentationTimeUs = videoExtra.getSampleTime();
            videoBufferInfo.flags = videoExtra.getSampleFlags();
            mediaMuxer.writeSampleData(videoIndex, videoBuffer, videoBufferInfo);

            videoExtra.advance();
        }



        while ((audioSize = musicExtra.readSampleData(audioBuffer, 0)) != -1) {
            audioBufferInfo.offset = 0;
            audioBufferInfo.size = audioSize;
            audioBufferInfo.presentationTimeUs = musicExtra.getSampleTime();
            audioBufferInfo.flags = musicExtra.getSampleFlags();
            mediaMuxer.writeSampleData(audioIndex, audioBuffer, audioBufferInfo);
            musicExtra.advance();
        }
        musicExtra.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);

        videoExtra.release();
        musicExtra.release();
        mediaMuxer.stop();
        mediaMuxer.release();

1 个答案:

答案 0 :(得分:2)

  1. 三个输入参数:

    String videoPath,String audioPath,String outputPath

  2. 获取视频时长及其音轨索引

        videoExtractor = new MediaExtractor();
        videoExtractor.setDataSource(videoPath);
        MediaFormat videoFormat = null;
    
        int videoTrackCount = videoExtractor.getTrackCount();
        //vedio max input size
        int frameMaxInputSize = 0;
        int frameRate = 0;
        long videoDuration = 0;
    
        for (int i = 0; i < videoTrackCount; i++) {
            videoFormat = videoExtractor.getTrackFormat(i);
            String mimeType = videoFormat.getString(MediaFormat.KEY_MIME);
            if (mimeType.startsWith("video/")) {
                /*
                 * just use the first track
                 */
                videoTrackIndex = i;
                frameMaxInputSize = videoFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
                frameRate = videoFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
                videoDuration = videoFormat.getLong(MediaFormat.KEY_DURATION);
                break;
            }
        }
    
        if (videoTrackIndex  < 0 ) {
            Log.e(TAG, "Error input file:: No Vedio track");
            return;
        }
    
  3. 获取音频信息

        audioExtractor = new MediaExtractor();
        audioExtractor.setDataSource(audioPath);
        MediaFormat audioFormat = null;
    
        int audioTrackCount = audioExtractor.getTrackCount();
        audioExtractor = new MediaExtractor();
        int audioTrackCount = audioExtractor.getTrackCount();
        for (int i = 0; i < audioTrackCount; i++) {
            audioFormat = audioExtractor.getTrackFormat(i);
            String mimeType = audioFormat.getString(MediaFormat.KEY_MIME);
            if (mimeType.startsWith("audio/")) {
                audioTrackIndex = i;
                break;
            }
        }
    
        if (audioTrackIndex  < 0 ) {
            Log.e(TAG, "Error input file:: No Audio track");
            return;
        }
    
  4. 写入视频数据:

        MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
        mediaMuxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
        int writeVideoTrackIndex = mediaMuxer.addTrack(videoFormat);
        int writeAudioTrackIndex = mediaMuxer.addTrack(audioFormat);
        mediaMuxer.start();
    
        ByteBuffer byteBuffer = ByteBuffer.allocate(frameMaxInputSize);
        videoExtractor.unselectTrack(videoTrackIndex);
        videoExtractor.selectTrack(videoTrackIndex);
    
        while (true) {
            int readVideoSampleSize = videoExtractor.readSampleData(byteBuffer, 0);
            if (readVideoSampleSize < 0) {
                videoExtractor.unselectTrack(videoTrackIndex);
                break;
            }
            long videoSampleTime = videoExtractor.getSampleTime();
            videoBufferInfo.size = readVideoSampleSize;
            videoBufferInfo.presentationTimeUs = videoSampleTime;
            //videoBufferInfo.presentationTimeUs += 1000 * 1000 / frameRate;
            videoBufferInfo.offset = 0;
            videoBufferInfo.flags = videoExtractor.getSampleFlags();
            mediaMuxer.writeSampleData(writeVideoTrackIndex, byteBuffer, videoBufferInfo);
            videoExtractor.advance();
        }
    
  5. 写入音频数据

        long audioPresentationTimeUs = 0;
        MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();
        audioExtractor.selectTrack(audioTrackIndex);
        /*
         * the last audio presentation time.
         */
        long lastEndAudioTimeUs = 0;
        while (true) {
            int readAudioSampleSize = audioExtractor.readSampleData(byteBuffer, 0);
            if (readAudioSampleSize < 0) {
                //if end of the stream, unselect
                audioExtractor.unselectTrack(audioTrackIndex);
                if (audioPresentationTimeUs >= videoDuration) {
                    //if has reach the end of the video time ,just exit
                    break;
                } else {
                    //if not the end of the video time, just repeat.
                    lastEndAudioTimeUs += audioPresentationTimeUs;
                    audioExtractor.selectTrack(audioTrackIndex);
                    continue;
                }
            }
    
            long audioSampleTime = audioExtractor.getSampleTime();
            audioBufferInfo.size = readAudioSampleSize;
            audioBufferInfo.presentationTimeUs = audioSampleTime + lastEndAudioTimeUs;
            if (audioBufferInfo.presentationTimeUs > videoDuration) {
                audioExtractor.unselectTrack(audioTrackIndex);
                break;
            }
            audioPresentationTimeUs = audioBufferInfo.presentationTimeUs;
            audioBufferInfo.offset = 0;
            audioBufferInfo.flags = audioExtractor.getSampleFlags();
            mediaMuxer.writeSampleData(writeAudioTrackIndex, byteBuffer, audioBufferInfo);
            audioExtractor.advance();
        }
    
  6. 释放资源。

       if (mediaMuxer != null) {
            try {
                mediaMuxer.stop();
                mediaMuxer.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        if (videoExtractor != null) {
            try {
                videoExtractor.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        if (audioExtractor != null) {
            try {
                audioExtractor.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

希望这会有所帮助!