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

  • Android: cómo reproducir video de los activos?
  • Reproducción de vídeo en TextureView
  • Integración de VLC o cualquier otro reproductor de video de terceros en la aplicación para Android
  • Cómo reproducir vídeos de YouTube en WebView en Amazon Fire TV?
  • Android: Transmitir datos de la cámara y escribirlos en el servidor
  • Reproductor de vídeo en android (desarrollar)
  • Android MediaRecorder produce video corrupto con líneas verdes
  • Los archivos de video locales no se reproducirán en la aplicación para Android de Cordova
  • Muestra una fuente de video de gstreamer en Google Cartón SurfaceTexture
  • Cómo manejar la orientación del vídeo desde dispositivos móviles
  • SetVideoSize () se bloquea con altas resoluciones
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.