¿Cómo mux archivo de audio y archivo de vídeo?

Tengo un archivo 3gp que se graba desde el micrófono y un archivo de vídeo mp4. Quiero mux archivo de audio y archivo de vídeo en un archivo mp4 y guardarlo. He buscado mucho pero no encontré nada útil para usar MediaMuxer api de android. MediaMuxer api

UPDATE: este es mi método que mux dos archivos, tengo una excepción en ella. Y la razón es que el archivo mp4 destino no tiene ninguna pista! Puede someOne ayudarme con la adición de pistas de audio y vídeo a muxer ??

Excepción

java.lang.IllegalStateException: Failed to stop the muxer 

mi código:

 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(); } 

UPDATE 2: problema resuelto! Revise mi respuesta a mi pregunta

gracias por tu ayuda

Tuve algún problema con pistas de archivos de audio y video. Se fueron y todo está bien con mi código, pero ahora se puede utilizar para fusionar un archivo de audio y un archivo de vídeo juntos .

Código:

 private void muxing() { String outputFile = ""; try { File file = new File(Environment.getExternalStorageDirectory() + File.separator + "final2.mp4"); file.createNewFile(); outputFile = file.getAbsolutePath(); MediaExtractor videoExtractor = new MediaExtractor(); AssetFileDescriptor afdd = getAssets().openFd("Produce.MP4"); videoExtractor.setDataSource(afdd.getFileDescriptor() ,afdd.getStartOffset(),afdd.getLength()); MediaExtractor audioExtractor = new MediaExtractor(); audioExtractor.setDataSource(audioFilePath); Log.d(TAG, "Video Extractor Track Count " + videoExtractor.getTrackCount() ); Log.d(TAG, "Audio Extractor Track Count " + audioExtractor.getTrackCount() ); MediaMuxer muxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); videoExtractor.selectTrack(0); MediaFormat videoFormat = videoExtractor.getTrackFormat(0); int videoTrack = muxer.addTrack(videoFormat); audioExtractor.selectTrack(0); MediaFormat audioFormat = audioExtractor.getTrackFormat(0); int audioTrack = muxer.addTrack(audioFormat); Log.d(TAG, "Video Format " + videoFormat.toString() ); Log.d(TAG, "Audio Format " + audioFormat.toString() ); boolean sawEOS = false; int frameCount = 0; int offset = 100; int sampleSize = 256 * 1024; ByteBuffer videoBuf = ByteBuffer.allocate(sampleSize); ByteBuffer audioBuf = ByteBuffer.allocate(sampleSize); MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo(); MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo(); videoExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC); audioExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC); muxer.start(); while (!sawEOS) { videoBufferInfo.offset = offset; videoBufferInfo.size = videoExtractor.readSampleData(videoBuf, offset); if (videoBufferInfo.size < 0 || audioBufferInfo.size < 0) { Log.d(TAG, "saw input EOS."); sawEOS = true; videoBufferInfo.size = 0; } else { videoBufferInfo.presentationTimeUs = videoExtractor.getSampleTime(); videoBufferInfo.flags = videoExtractor.getSampleFlags(); muxer.writeSampleData(videoTrack, videoBuf, videoBufferInfo); videoExtractor.advance(); frameCount++; Log.d(TAG, "Frame (" + frameCount + ") Video PresentationTimeUs:" + videoBufferInfo.presentationTimeUs +" Flags:" + videoBufferInfo.flags +" Size(KB) " + videoBufferInfo.size / 1024); Log.d(TAG, "Frame (" + frameCount + ") Audio PresentationTimeUs:" + audioBufferInfo.presentationTimeUs +" Flags:" + audioBufferInfo.flags +" Size(KB) " + audioBufferInfo.size / 1024); } } Toast.makeText(getApplicationContext() , "frame:" + frameCount , Toast.LENGTH_SHORT).show(); boolean sawEOS2 = false; int frameCount2 =0; while (!sawEOS2) { frameCount2++; audioBufferInfo.offset = offset; audioBufferInfo.size = audioExtractor.readSampleData(audioBuf, offset); if (videoBufferInfo.size < 0 || audioBufferInfo.size < 0) { Log.d(TAG, "saw input EOS."); sawEOS2 = true; audioBufferInfo.size = 0; } else { audioBufferInfo.presentationTimeUs = audioExtractor.getSampleTime(); audioBufferInfo.flags = audioExtractor.getSampleFlags(); muxer.writeSampleData(audioTrack, audioBuf, audioBufferInfo); audioExtractor.advance(); Log.d(TAG, "Frame (" + frameCount + ") Video PresentationTimeUs:" + videoBufferInfo.presentationTimeUs +" Flags:" + videoBufferInfo.flags +" Size(KB) " + videoBufferInfo.size / 1024); Log.d(TAG, "Frame (" + frameCount + ") Audio PresentationTimeUs:" + audioBufferInfo.presentationTimeUs +" Flags:" + audioBufferInfo.flags +" Size(KB) " + audioBufferInfo.size / 1024); } } Toast.makeText(getApplicationContext() , "frame:" + frameCount2 , Toast.LENGTH_SHORT).show(); muxer.stop(); muxer.release(); } catch (IOException e) { Log.d(TAG, "Mixer Error 1 " + e.getMessage()); } catch (Exception e) { Log.d(TAG, "Mixer Error 2 " + e.getMessage()); } 

}

Gracias a estos códigos de ejemplo: Códigos de ejemplo de MediaMuxer : realmente perfecto

Gracias mohamad ali gharat para esta respuesta, es ayudarme demasiado. Pero hay un cambio que hice al código para trabajar, primero: cambio

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

Para cargar vídeo desde SDCard . Segundo: Consigo error con

videoBufferInfo.flags = videoExtractor.getSampleFlags();

Así que cambia a

videoBufferInfo.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;

Para que funcione como este enlace dice que Android MediaMuxer no pudo detener

Lo que necesitará para trabajar en ffmpeg. Aquí hay un enlace para ayudar con eso:

FFmpeg en Android

Ffmpeg requiere el NDK en Android.

Una vez que tenga ese trabajo, puede trabajar en muxing el audio y el video juntos usando ffmpeg. Aquí hay un enlace a una pregunta que lo hace con 2 archivos de vídeo (la respuesta debería ser similar).

FFMPEG mux vídeo y audio (de otro video) – problema de mapeo

  • Android :: VideoView dentro de un ScrollView
  • MediaCodec problemas de muxing de audio / video y Android
  • Cómo transmitir vídeo desde Internet a través de nanoHTTPd a VideoView
  • La reproducción de vídeo proporciona pantalla en negro pero con sonido
  • Transmisión en directo del reproductor RTMP / RTSP sin utilizar la visualización web (servidor WOWZA) en Android
  • ¿Es posible grabar vídeo de la cámara a través de un búfer en un archivo?
  • Streaming to VideoView sólo se reproduce en Wifi cuando se utilizan teléfonos Samsung
  • Cómo ocultar la ventana Intent Chooser en android?
  • Android no puede reproducir vídeo H264 / AAC
  • Reproducción de vídeo a cámara lenta en android
  • ¿Qué es AwesomePlayer en android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.