使用 MediaExtractor 和 MediaMuxer 创建视频会生成比原始视频持续时间更短的视频
Creating a video with MediaExtractor and MediaMuxer produces a video with shorter duration than the original one
出于测试目的,我使用 MediaExtractor 和 MediaMuxer 从现有视频创建新视频。我希望新视频的持续时间与原始视频完全相同,但事实并非如此。新视频时长比原视频略短
fun test(firstVideo: FileDescriptor, outputFileAbsolutePathUri: String) {
val extractor = MediaExtractor().apply {
this.setDataSource(firstVideo)
}
val muxer = MediaMuxer(outputFileAbsolutePathUri, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
try {
val MAX_SAMPLE_SIZE = 20 * 1024 * 1024
val bufferSize: Int = MAX_SAMPLE_SIZE
val dstBuf: ByteBuffer = ByteBuffer.allocate(bufferSize)
val bufferInfo = MediaCodec.BufferInfo()
val indexMap = setMuxerTracks(extractor, muxer)
muxer.start()
muxDataFromExtractor(muxer, extractor, indexMap, dstBuf, bufferInfo)
muxer.stop()
} finally {
extractor.release()
muxer.release()
}
}
private fun setMuxerTracks(extractor: MediaExtractor, muxer: MediaMuxer): Map<Int, Int> {
val indexMap = HashMap<Int, Int>(extractor.trackCount)
for (i in 0 until extractor.trackCount) {
extractor.selectTrack(i)
val format: MediaFormat = extractor.getTrackFormat(i)
val dstIndex = muxer.addTrack(format)
indexMap[i] = dstIndex
}
return indexMap
}
private fun muxDataFromExtractor(muxer: MediaMuxer,
extractor: MediaExtractor,
trackIndexMap: Map<Int, Int>,
dstBuf: ByteBuffer,
bufferInfo: MediaCodec.BufferInfo) {
var sawEOS = false
val initialPresentationTimeUs = bufferInfo.presentationTimeUs
while (!sawEOS) {
bufferInfo.offset = 0
bufferInfo.size = extractor.readSampleData(dstBuf, 0)
if (bufferInfo.size < 0) {
sawEOS = true
bufferInfo.size = 0
} else {
bufferInfo.presentationTimeUs = initialPresentationTimeUs + extractor.sampleTime
bufferInfo.flags = extractor.sampleFlags
val trackIndex = extractor.sampleTrackIndex
muxer.writeSampleData(trackIndexMap[trackIndex]!!, dstBuf, bufferInfo)
extractor.advance()
}
}
}
为了比较,原始视频时长为 3366666 微秒,创建的视频时长为 3366366 微秒。从 MediaFormat (MediaFormat.KEY_DURATION)
中检索视频长度
没有答案,但一些输入可能有帮助:
我相信媒体提取器和媒体混合器是供应商所有的,google 有默认的 cpp 实现,但供应商可以覆盖它。您可以在此处查看 google 实施:
https://cs.android.com/android/platform/superproject/+/master:frameworks/av/media/libstagefright/MediaMuxer.cpp;l=173
它帮助我解决了引擎中与“最后一帧”/时间不匹配相关的一个巫毒错误。注意:您需要确保您正在查看正确的版本(检查右侧的 blame 工具)。
媒体可以包含创建文件时推送的任何元数据值。所以,你可以重新计算它或者只使用你得到的。
您是否尝试过拍摄您创建的视频,然后 运行 在输入此文件时进行测试?
这似乎取决于源视频的创建方式:当我使用 ffprobe 获取源视频元数据时,我得到以下信息:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'source.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.76.100
Duration: 00:00:03.37, start: 0.000000, bitrate: 123 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 400x136, 118 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
handler_name : Core Media Video
结果视频元数据为:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'result.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2022-01-06T12:01:21.000000Z
com.android.version: 11
Duration: 00:00:03.37, start: 0.000000, bitrate: 126 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 400x136, 118 kb/s, SAR 1:1 DAR 50:17, 30 fps, 30 tbr, 90k tbn, 60 tbc (default)
Metadata:
creation_time : 2022-01-06T12:01:21.000000Z
handler_name : VideoHandle
当我使用通过 MediaExtractor 和 MediaMuxer 创建的视频作为源时,视频持续时间相同(在 1 微秒阈值内)
出于测试目的,我使用 MediaExtractor 和 MediaMuxer 从现有视频创建新视频。我希望新视频的持续时间与原始视频完全相同,但事实并非如此。新视频时长比原视频略短
fun test(firstVideo: FileDescriptor, outputFileAbsolutePathUri: String) {
val extractor = MediaExtractor().apply {
this.setDataSource(firstVideo)
}
val muxer = MediaMuxer(outputFileAbsolutePathUri, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
try {
val MAX_SAMPLE_SIZE = 20 * 1024 * 1024
val bufferSize: Int = MAX_SAMPLE_SIZE
val dstBuf: ByteBuffer = ByteBuffer.allocate(bufferSize)
val bufferInfo = MediaCodec.BufferInfo()
val indexMap = setMuxerTracks(extractor, muxer)
muxer.start()
muxDataFromExtractor(muxer, extractor, indexMap, dstBuf, bufferInfo)
muxer.stop()
} finally {
extractor.release()
muxer.release()
}
}
private fun setMuxerTracks(extractor: MediaExtractor, muxer: MediaMuxer): Map<Int, Int> {
val indexMap = HashMap<Int, Int>(extractor.trackCount)
for (i in 0 until extractor.trackCount) {
extractor.selectTrack(i)
val format: MediaFormat = extractor.getTrackFormat(i)
val dstIndex = muxer.addTrack(format)
indexMap[i] = dstIndex
}
return indexMap
}
private fun muxDataFromExtractor(muxer: MediaMuxer,
extractor: MediaExtractor,
trackIndexMap: Map<Int, Int>,
dstBuf: ByteBuffer,
bufferInfo: MediaCodec.BufferInfo) {
var sawEOS = false
val initialPresentationTimeUs = bufferInfo.presentationTimeUs
while (!sawEOS) {
bufferInfo.offset = 0
bufferInfo.size = extractor.readSampleData(dstBuf, 0)
if (bufferInfo.size < 0) {
sawEOS = true
bufferInfo.size = 0
} else {
bufferInfo.presentationTimeUs = initialPresentationTimeUs + extractor.sampleTime
bufferInfo.flags = extractor.sampleFlags
val trackIndex = extractor.sampleTrackIndex
muxer.writeSampleData(trackIndexMap[trackIndex]!!, dstBuf, bufferInfo)
extractor.advance()
}
}
}
为了比较,原始视频时长为 3366666 微秒,创建的视频时长为 3366366 微秒。从 MediaFormat (MediaFormat.KEY_DURATION)
中检索视频长度没有答案,但一些输入可能有帮助:
我相信媒体提取器和媒体混合器是供应商所有的,google 有默认的 cpp 实现,但供应商可以覆盖它。您可以在此处查看 google 实施: https://cs.android.com/android/platform/superproject/+/master:frameworks/av/media/libstagefright/MediaMuxer.cpp;l=173
它帮助我解决了引擎中与“最后一帧”/时间不匹配相关的一个巫毒错误。注意:您需要确保您正在查看正确的版本(检查右侧的 blame 工具)。
媒体可以包含创建文件时推送的任何元数据值。所以,你可以重新计算它或者只使用你得到的。
您是否尝试过拍摄您创建的视频,然后 运行 在输入此文件时进行测试?
这似乎取决于源视频的创建方式:当我使用 ffprobe 获取源视频元数据时,我得到以下信息:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'source.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.76.100
Duration: 00:00:03.37, start: 0.000000, bitrate: 123 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 400x136, 118 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
handler_name : Core Media Video
结果视频元数据为:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'result.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2022-01-06T12:01:21.000000Z
com.android.version: 11
Duration: 00:00:03.37, start: 0.000000, bitrate: 126 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 400x136, 118 kb/s, SAR 1:1 DAR 50:17, 30 fps, 30 tbr, 90k tbn, 60 tbc (default)
Metadata:
creation_time : 2022-01-06T12:01:21.000000Z
handler_name : VideoHandle
当我使用通过 MediaExtractor 和 MediaMuxer 创建的视频作为源时,视频持续时间相同(在 1 微秒阈值内)