簡體   English   中英

使用 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) 中檢索視頻長度

沒有答案,但一些輸入可能會有所幫助:

  1. 我相信媒體提取器和媒體復用器是供應商擁有的,谷歌有默認的 cpp 實現,但供應商可以覆蓋它。 你可以在這里查看谷歌的實現: https://cs.android.com/android/platform/superproject/+/master:frameworks/av/media/libstagefright/MediaMuxer.cpp;l=173

    它幫助我解決了引擎中與“最后一幀”/時間不匹配相關的一個巫毒錯誤。 注意:您需要確保您正在查看正確的版本(檢查右側的責備工具)。

  2. 媒體可以包含創建文件時推送的任何元數據值。 所以,你可以再次計算它或只使用你得到的。

  3. 您是否嘗試拍攝您創建的視頻,然后在輸入此文件時運行測試?

看來這取決於源視頻的創建方式:當我使用 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 微秒閾值內)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM