MediaCodec을 사용하여 화면 캡처와 오디오를 녹음하는 앱을 쓰고 있습니다. 필자는 MediaMuxer를 사용하여 mp4 파일을 만들기 위해 비디오와 오디오를 혼합합니다. 필자는 비디오와 오디오를 별도로 기록하는 데 성공했지만, 라이브를 함께 멀티플렉싱하면 결과가 예상치 않게됩니다. 오디오는 비디오없이 재생되거나 비디오는 오디오 직후에 재생됩니다. 내 생각 엔 타임 스탬프에 문제가있는 것 같지만 정확히 무엇을 파악할 수없는 것입니다. 이미 그 예를 보았습니다 : https://github.com/OnlyInAmerica/HWEncoderExperiments/tree/audiotest/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments과 bigflake.com에있는 것들이 답을 찾을 수 없었습니다. 에오디오와 비디오를 다중화 할 수 없습니다.
mInputSurface.setPresentationTime(mSurfaceTexture.getTimestamp());
drainVideoEncoder(false);
그리고이 : 나는 비디오 타임 스탬프를 설정하려면이 옵션을 사용
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;
:
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;
}
오디오 및 비디오 인코더, 먹서 :
여기 내 미디어 형식의 구성이다 오디오 시간 스탬프 설정 :
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;
}
나는 "timestampUs XXX < lastTimestampUs XXX"오류를 방지하기 위해이 예 https://github.com/OnlyInAmerica/HWEncoderExperiments/blob/audiotest/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments/AudioEncodingTest.java에서했다
이누군가가 나에게 문제를하시기 바랍니다 알아내는 데 도움이 수 있습니까?
덕분에 많은 fadden, 나는 오디오 및 비디오 동기화 할 수 있었다! 당신은 대단하다 :) – Alexey
나는 하나 더 작은 문제를 가지고있다. 오디오없이 오디오를 재생하면 내 녹음이 더 빨리 재생됩니다. 그리고 오디오 트랙이 왜곡 된 것처럼 보입니다. 오디오가 각 비디오 프레임과 청크에 의해 청크로 작성되기 때문에 이런 일이 발생한다고 생각합니다. 기록 할 청크의 크기는 fps 및 샘플 속도에 따라 계산됩니다. 내 fps가 크게 달라지기 때문에 오디오는 불균등 한 덩어리 때문에 왜곡됩니다. 어쩌면 당신은 그것을 다루는 방법에 대한 제안이 있습니까? – Alexey
불행히도 나는 오디오를 많이하지 않았다. 오디오 타임 스탬프는 현재 어디에서 제공됩니까? 비디오 타임 스탬프 (SurfaceTexture 타임 스탬프)에 대한 좋은 출처가 있습니다. 오디오와 비슷한 것을 사용하고 있거나, System.nanoTime()으로 위장한 것일 것입니다. (미디어 물건은 일반적으로 System.nanoTime()과 같은 시스템 단조 클럭을 사용하지만 일부 부분은 나노초가 아닌 마이크로 초를 사용합니다. – fadden