¿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 ??
- No se muestra el video web de Android HoneyComb
- Android: graba vídeo en la misma orientación independientemente de la orientación del dispositivo
- Android MediaRecorder produce video corrupto con líneas verdes
- ¿Cómo puedo capturar una grabación de vídeo en Android?
- Pruebe a grabar vídeo utilizando la shell de adb screenrecord Android 4.4
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
- Video vía phonegap en android
- Recortar video como whatsapp
- Android Mostrar MediaController
- Cómo reproducir el archivo de vídeo de formato .mov en la aplicación android
- Vídeo con iframe no se muestra en la vista web de Android
- PhoneGap Android - Reproducción de vídeos locales
- El video no se reproduce en la vista web de Android
- Cómo reproducir URL de vídeo dentro de la vista web de Android
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
avideoExtractor.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
- ¿Cuál es el método compat para usar finishAffinity () para API 14?
- Android Dagger 2 POJO campo Inyectar null