android - 如何复用音频文件和视频文件?

时间:2015-07-22 19:15:22

标签: android video mediamuxer

我有一个从麦克风录制的3gp文件和一个mp4视频文件。 我想将音频文件和视频文件复制到mp4文件并保存。 我搜索了很多,但没有找到任何有助于使用Android的MediaMuxer api的东西。 MediaMuxer api

更新:这是我的方法,复用两个文件,我有一个例外。 原因是目标mp4文件没有任何轨道! someOne可以帮我添加音频和视频轨道到muxer ??

例外

java.lang.IllegalStateException: Failed to stop the muxer

我的代码:

private void cloneMediaUsingMuxer( String dstMediaPath) throws IOException {
    // Set up MediaExtractor to read from the source.
    MediaExtractor soundExtractor = new MediaExtractor();
    soundExtractor.setDataSource(audioFilePath);
    MediaExtractor videoExtractor = new MediaExtractor();
    AssetFileDescriptor afd2 = getAssets().openFd("Produce.MP4");
    videoExtractor.setDataSource(afd2.getFileDescriptor() , afd2.getStartOffset(),afd2.getLength());


    //PATH
    //extractor.setDataSource();
    int trackCount = soundExtractor.getTrackCount();
    int trackCount2 = soundExtractor.getTrackCount();

    //assertEquals("wrong number of tracks", expectedTrackCount, trackCount);
    // Set up MediaMuxer for the destination.
    MediaMuxer muxer;
    muxer = new MediaMuxer(dstMediaPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
    // Set up the tracks.
    HashMap<Integer, Integer> indexMap = new HashMap<Integer, Integer>(trackCount);
    for (int i = 0; i < trackCount; i++) {
        soundExtractor.selectTrack(i);
        MediaFormat SoundFormat = soundExtractor.getTrackFormat(i);
        int dstIndex = muxer.addTrack(SoundFormat);
        indexMap.put(i, dstIndex);
    }

    HashMap<Integer, Integer> indexMap2 = new HashMap<Integer, Integer>(trackCount2);
    for (int i = 0; i < trackCount2; i++) {
        videoExtractor.selectTrack(i);
        MediaFormat videoFormat = videoExtractor.getTrackFormat(i);
        int dstIndex2 = muxer.addTrack(videoFormat);
        indexMap.put(i, dstIndex2);
    }


    // Copy the samples from MediaExtractor to MediaMuxer.
    boolean sawEOS = false;
    int bufferSize = MAX_SAMPLE_SIZE;
    int frameCount = 0;
    int offset = 100;
    ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
    MediaCodec.BufferInfo bufferInfo2 = new MediaCodec.BufferInfo();

    muxer.start();
    while (!sawEOS) {
        bufferInfo.offset = offset;
        bufferInfo.size = soundExtractor.readSampleData(dstBuf, offset);
        bufferInfo2.offset = offset;
        bufferInfo2.size = videoExtractor.readSampleData(dstBuf, offset);

        if (bufferInfo.size < 0) {
            sawEOS = true;
            bufferInfo.size = 0;
            bufferInfo2.size = 0;
        }else if(bufferInfo2.size < 0){
            sawEOS = true;
            bufferInfo.size = 0;
            bufferInfo2.size = 0;
        }
        else {
            bufferInfo.presentationTimeUs = soundExtractor.getSampleTime();
            bufferInfo2.presentationTimeUs = videoExtractor.getSampleTime();
            //bufferInfo.flags = extractor.getSampleFlags();
            int trackIndex = soundExtractor.getSampleTrackIndex();
            int trackIndex2 = videoExtractor.getSampleTrackIndex();
            muxer.writeSampleData(indexMap.get(trackIndex), dstBuf,
                    bufferInfo);

            soundExtractor.advance();
            videoExtractor.advance();
            frameCount++;

        }
    }

    Toast.makeText(getApplicationContext(),"f:"+frameCount,Toast.LENGTH_SHORT).show();

    muxer.stop();
    muxer.release();

}

更新2:问题解决了!检查我的问题的答案。

感谢您的帮助

3 个答案:

答案 0 :(得分:17)

音频和视频文件的音轨存在问题。 他们走了,我的代码一切正常,但现在你可以用它来合并一个音频文件和一个视频文件

代码:

[JAVA-4, JAVA-3, JAVA-2, CPP-2, JAVA-1, CPP-1, C]

}

感谢这些示例代码:MediaMuxer Sample Codes-really perfect

答案 1 :(得分:1)

感谢mohamad ali gharat的回答,这对我帮助太大了。 但是我对代码工作做了一些改变, 第一:我改变了

  

videoExtractor.setDataSource来   videoExtractor.setDataSource(Environment.getExternalStorageDirectory().getPath() + "/Produce.MP4");

SDCard加载视频。 第二:我错了

  

videoBufferInfo.flags = videoExtractor.getSampleFlags();

所以将其改为

  

videoBufferInfo.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;

使其工作,因为此链接说Android MediaMuxer failed to stop

答案 2 :(得分:0)

你需要在ffmpeg工作。这是一个帮助的链接:

FFmpeg on Android

ffmpeg需要Android上的NDK。

一旦你有了这个工作,你就可以使用ffmpeg将音频和视频混合在一起了。这是一个用2个视频文件做的问题的链接(答案应该类似)。

FFMPEG mux video and audio (from another video) - mapping issue