No se puede mux tanto de audio como de vídeo

Estoy escribiendo una aplicación que registra captura de pantalla y audio usando MediaCodec. Yo uso MediaMuxer mux vídeo y audio para crear archivo mp4. He conseguido escribir vídeo y audio por separado, sin embargo, cuando intento muxing juntos en vivo, el resultado es inesperado. El audio se reproduce sin vídeo o el video se reproduce justo después del audio. Mi suposición es que estoy haciendo algo mal con marcas de tiempo, pero no puedo averiguar qué exactamente. Ya he mirado esos ejemplos: https://github.com/OnlyInAmerica/HWEncoderExperiments/tree/audiotest/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments y los de bigflake.com y no fue capaz de encontrar el responder.

He aquí mis configuraciones de formatos de medios:

mVideoFormat = createMediaFormat(); private static MediaFormat createVideoFormat() { MediaFormat format = MediaFormat.createVideoFormat( Preferences.MIME_TYPE, mScreenWidth, mScreenHeight); format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); format.setInteger(MediaFormat.KEY_BIT_RATE, Preferences.BIT_RATE); format.setInteger(MediaFormat.KEY_FRAME_RATE, Preferences.FRAME_RATE); format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, Preferences.IFRAME_INTERVAL); return format; } mAudioFormat = createAudioFormat(); private static MediaFormat createAudioFormat() { MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm"); format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); format.setInteger(MediaFormat.KEY_BIT_RATE, 64000); return format; } 

Codificadores de audio y video, muxer:

  mVideoEncoder = MediaCodec.createEncoderByType(Preferences.MIME_TYPE); mVideoEncoder.configure(mVideoFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mInputSurface = new InputSurface(mVideoEncoder.createInputSurface(), mSavedEglContext); mVideoEncoder.start(); if (recordAudio){ audioBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); mAudioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, audioBufferSize); mAudioRecorder.startRecording(); mAudioEncoder = MediaCodec.createEncoderByType("audio/mp4a-latm"); mAudioEncoder.configure(mAudioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mAudioEncoder.start(); } try { String fileId = String.valueOf(System.currentTimeMillis()); mMuxer = new MediaMuxer(dir.getPath() + "/Video" + fileId + ".mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); } catch (IOException ioe) { throw new RuntimeException("MediaMuxer creation failed", ioe); } mVideoTrackIndex = -1; mAudioTrackIndex = -1; mMuxerStarted = false; 

Yo uso esto para configurar timestamps de video:

 mInputSurface.setPresentationTime(mSurfaceTexture.getTimestamp()); drainVideoEncoder(false); 

Y esto para configurar los sellos de tiempo de audio:

 lastQueuedPresentationTimeStampUs = getNextQueuedPresentationTimeStampUs(); if(endOfStream) mAudioEncoder.queueInputBuffer(inputBufferIndex, 0, audioBuffer.length, lastQueuedPresentationTimeStampUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); else mAudioEncoder.queueInputBuffer(inputBufferIndex, 0, audioBuffer.length, lastQueuedPresentationTimeStampUs, 0); mAudioBufferInfo.presentationTimeUs = getNextDeQueuedPresentationTimeStampUs(); mMuxer.writeSampleData(mAudioTrackIndex, encodedData, mAudioBufferInfo); lastDequeuedPresentationTimeStampUs = mAudioBufferInfo.presentationTimeUs; private static long getNextQueuedPresentationTimeStampUs(){ long nextQueuedPresentationTimeStampUs = (lastQueuedPresentationTimeStampUs > lastDequeuedPresentationTimeStampUs) ? (lastQueuedPresentationTimeStampUs + 1) : (lastDequeuedPresentationTimeStampUs + 1); Log.i(TAG, "nextQueuedPresentationTimeStampUs: " + nextQueuedPresentationTimeStampUs); return nextQueuedPresentationTimeStampUs; } private static long getNextDeQueuedPresentationTimeStampUs(){ Log.i(TAG, "nextDequeuedPresentationTimeStampUs: " + (lastDequeuedPresentationTimeStampUs + 1)); lastDequeuedPresentationTimeStampUs ++; return lastDequeuedPresentationTimeStampUs; } 

Lo tomé de este ejemplo https://github.com/OnlyInAmerica/HWEncoderExperiments/blob/audiotest/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments/AudioEncodingTest.java con el fin de evitar "timestampUs XXX <lastTimestampUs XXX" error

¿Puede alguien ayudarme a resolver el problema, por favor?

2 Solutions collect form web for “No se puede mux tanto de audio como de vídeo”

Parece que está utilizando estampas de tiempo proporcionadas por el sistema para el vídeo, pero un simple contador para el audio. A menos que de alguna manera se use la marca de tiempo de video para sembrar el audio de cada fotograma y no se muestra arriba.

Para que el audio y el vídeo se reproduzcan en sincronía, debe tener la misma marca de tiempo de presentación en los marcos de audio y vídeo que se espera que se presenten al mismo tiempo.

Véase también esta pregunta relacionada .

Creo que la solución podría ser sólo leer repetidamente las muestras de audio. Podría comprobar si un nuevo cuadro de video está disponible cada N muestras de audio y pasarlo al muxer con la misma marca de tiempo tan pronto como llegue un nuevo marco de vídeo.

 int __buffer_offset = 0; final int CHUNK_SIZE = 100; /* record 100 samples each iteration */ while (!__new_video_frame_available) { this._audio_recorder.read(__recorded_data, __buffer_offset, CHUNK_SIZE); __buffer_offset += CHUNK_SIZE; } 

Creo que debería funcionar.

Saludos cordiales, Wolfram

  • Reproductor de vídeo en android (desarrollar)
  • Reproducción de archivos .m3u8 a través de HTTPS en android 2.3
  • Android Intent.ACTION_VIEW
  • Cómo jugar un video en Cordova 3.4.0 - Android
  • Android Crear miniatura de video en un momento específico
  • Corregir archivo 3GP después de la transmisión desde Android Media Recorder
  • Extraer fotogramas de vídeo en Android
  • Android: Reproducción y grabación simultánea de vídeo
  • Limitaciones de la captura de video en la brecha del teléfono + complementos nativos
  • Decodificación de flujo de vídeo en Android de DJI drone
  • Establecer brillo / contraste en la captura de vídeo con Android Camera2
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.