亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

C# 版 flvmerge:快速合并多個flv文件

系統 2282 0

C# 版 flvmerge:快速合并多個flv文件

?

網上的視頻很多都是分片的 flv 文件,怎么把他們合為一體呢? GUI 工具就不考慮了,不適合批量執行,不適合在后臺運行。有沒有命令行工具或庫可以實現呢?

ffmpeg ? 提供了一個方法:

(1)先把 flv 文件轉換成 mpeg

(2)將多個 mpeg 文件合并成 1 個獨立的 mpeg 文件(二進制合并即可)

(3)將獨立的 mpeg 文件轉換成獨立的 flv 文件。

?網上搜到的最多的也是這種解決辦法。這種方法有兩個缺點:

(1)需要兩遍轉碼,非常耗時;

(2)轉換后的獨立的 mpeg 文件比原視頻要短一點點。

?木有辦法了,只好另尋他路。有人說有一個 flvmerge.exe? 程序可以將多個 flv 合并成一個,可惜的是俺搜了很久,都沒找到這個程序,最后還是在一款免費軟件里把這個“ flvmerge.exe ”文件給揪出來了,不幸的是,這個“ flvmerge.exe ”得不到正確的結果。

潤之同學說過,自己動手,豐衣足食。上? github? 上搜“ flvmerge ”,發現兩個項目,“ flvmerge ”和“ flvmerger ”,都是 C 寫的。前者不依賴于第三方庫,后者依賴于第三方庫,那么就從第一個開始吧。

看了看它的代碼,知道了 flv 文件合并的原理:

(1)?flv? 文件由 1 header 和若干個 tag 組成;

(2)?header 記錄了視頻的元數據;

(3)?tag? 是有時間戳的數據;

(4)?flv 合并的原理就是把多個文件里的 tag 組裝起來,調整各 tag 的時間戳,再在文件起始處按個頭部。

下面是我參照? flvmerge? 項目,用 linqpad 寫的一個 C# 版本的? flvmerge? 代碼:

?

          
              1
          
          
            void
          
          
             Main()


          
          
              2
          
          
            {


          
          
              3
          
               String path1 = 
          
            "
          
          
            D:\\Videos\\Subtitle\\OutputCache\\1.flv
          
          
            "
          
          
            ;


          
          
              4
          
               String path2 = 
          
            "
          
          
            D:\\Videos\\Subtitle\\OutputCache\\2.flv
          
          
            "
          
          
            ;


          
          
              5
          
               String path3 = 
          
            "
          
          
            D:\\Videos\\Subtitle\\OutputCache\\3.flv
          
          
            "
          
          
            ;


          
          
              6
          
               String output = 
          
            "
          
          
            D:\\Videos\\Subtitle\\OutputCache\\output.flv
          
          
            "
          
          
            ;


          
          
              7
          
          
              8
          
          
            using
          
          (FileStream fs1 = 
          
            new
          
          
             FileStream(path1, FileMode.Open))


          
          
              9
          
          
            using
          
          (FileStream fs2 = 
          
            new
          
          
             FileStream(path2, FileMode.Open))


          
          
             10
          
          
            using
          
          (FileStream fs3 = 
          
            new
          
          
             FileStream(path3, FileMode.Open))


          
          
             11
          
          
            using
          
          (FileStream fsMerge = 
          
            new
          
          
             FileStream(output, FileMode.Create))


          
          
             12
          
          
                {


          
          
             13
          
          
                    Console.WriteLine(IsFLVFile(fs1));


          
          
             14
          
          
                    Console.WriteLine(IsFLVFile(fs2));


          
          
             15
          
          
                    Console.WriteLine(IsFLVFile(fs3));


          
          
             16
          
          
             17
          
          
            if
          
          (IsSuitableToMerge(GetFLVFileInfo(fs1),GetFLVFileInfo(fs2)) == 
          
            false
          
          
             18
          
                       || IsSuitableToMerge(GetFLVFileInfo(fs1),GetFLVFileInfo(fs3)) == 
          
            false
          
          
            )


          
          
             19
          
          
                    {


          
          
             20
          
                       Console.WriteLine(
          
            "
          
          
            Video files not suitable to merge
          
          
            "
          
          
            );


          
          
             21
          
          
                    }


          
          
             22
          
          
             23
          
          
            int
          
           time = Merge(fs1,fsMerge,
          
            true
          
          ,
          
            0
          
          
            );


          
          
             24
          
                   time =  Merge(fs2,fsMerge,
          
            false
          
          
            ,time);


          
          
             25
          
                   time =  Merge(fs3,fsMerge,
          
            false
          
          
            ,time);


          
          
             26
          
                   Console.WriteLine(
          
            "
          
          
            Merge finished
          
          
            "
          
          
            );


          
          
             27
          
          
                }


          
          
             28
          
          
            }


          
          
             29
          
          
             30
          
          
            const
          
          
            int
          
           FLV_HEADER_SIZE = 
          
            9
          
          
            ;


          
          
             31
          
          
            const
          
          
            int
          
           FLV_TAG_HEADER_SIZE = 
          
            11
          
          
            ;


          
          
             32
          
          
            const
          
          
            int
          
           MAX_DATA_SIZE = 
          
            16777220
          
          
            ;


          
          
             33
          
          
             34
          
          
            class
          
          
             FLVContext


          
          
             35
          
          
            {


          
          
             36
          
          
            public
          
          
            byte
          
          
             soundFormat;


          
          
             37
          
          
            public
          
          
            byte
          
          
             soundRate;


          
          
             38
          
          
            public
          
          
            byte
          
          
             soundSize;


          
          
             39
          
          
            public
          
          
            byte
          
          
             soundType;


          
          
             40
          
          
            public
          
          
            byte
          
          
             videoCodecID;


          
          
             41
          
          
            }


          
          
             42
          
          
             43
          
          
            bool
          
          
             IsSuitableToMerge(FLVContext flvCtx1, FLVContext flvCtx2)


          
          
             44
          
          
            {


          
          
             45
          
          
            return
          
           (flvCtx1.soundFormat == flvCtx2.soundFormat) &&


          
             46
          
                 (flvCtx1.soundRate == flvCtx2.soundRate) &&


          
             47
          
                 (flvCtx1.soundSize == flvCtx2.soundSize) &&


          
             48
          
                 (flvCtx1.soundType == flvCtx2.soundType) &&


          
             49
          
                 (flvCtx1.videoCodecID ==
          
             flvCtx2.videoCodecID);


          
          
             50
          
          
            }


          
          
             51
          
          
             52
          
          
            bool
          
          
             IsFLVFile(FileStream fs)


          
          
             53
          
          
            {


          
          
             54
          
          
            int
          
          
             len;


          
          
             55
          
          
            byte
          
          [] buf = 
          
            new
          
          
            byte
          
          
            [FLV_HEADER_SIZE];


          
          
             56
          
               fs.Position = 
          
            0
          
          
            ;


          
          
             57
          
          
            if
          
          ( FLV_HEADER_SIZE != fs.Read(buf,
          
            0
          
          
            ,buf.Length))


          
          
             58
          
          
            return
          
          
            false
          
          
            ;


          
          
             59
          
          
             60
          
          
            if
          
           (buf[
          
            0
          
          ] != 
          
            '
          
          
            F
          
          
            '
          
           || buf[
          
            1
          
          ] != 
          
            '
          
          
            L
          
          
            '
          
           || buf[
          
            2
          
          ] != 
          
            '
          
          
            V
          
          
            '
          
           || buf[
          
            3
          
          ] != 
          
            0x01
          
          
            )


          
          
             61
          
          
            return
          
          
            false
          
          
            ;


          
          
             62
          
          
            else
          
          
             63
          
          
            return
          
          
            true
          
          
            ;


          
          
             64
          
          
            }


          
          
             65
          
          
             66
          
          
            FLVContext GetFLVFileInfo(FileStream fs)


          
          
             67
          
          
            {


          
          
             68
          
          
            bool
          
          
             hasAudioParams, hasVideoParams;


          
          
             69
          
          
            int
          
          
             skipSize, readLen;


          
          
             70
          
          
            int
          
          
             dataSize;


          
          
             71
          
          
            byte
          
          
             tagType;


          
          
             72
          
          
            byte
          
          [] tmp = 
          
            new
          
          
            byte
          
          [FLV_TAG_HEADER_SIZE+
          
            1
          
          
            ];


          
          
             73
          
          
            if
          
           (fs == 
          
            null
          
          ) 
          
            return
          
          
            null
          
          
            ;


          
          
             74
          
          
             75
          
               FLVContext flvCtx = 
          
            new
          
          
             FLVContext();


          
          
             76
          
               fs.Position = 
          
            0
          
          
            ;


          
          
             77
          
               skipSize = 
          
            9
          
          
            ;


          
          
             78
          
               fs.Position +=
          
             skipSize;


          
          
             79
          
               hasVideoParams = hasAudioParams = 
          
            false
          
          
            ;


          
          
             80
          
               skipSize = 
          
            4
          
          
            ;


          
          
             81
          
          
            while
          
           (!hasVideoParams || !
          
            hasAudioParams)


          
          
             82
          
          
                {


          
          
             83
          
                   fs.Position +=
          
             skipSize;


          
          
             84
          
          
             85
          
          
            if
          
           (FLV_TAG_HEADER_SIZE+
          
            1
          
           != fs.Read(tmp,
          
            0
          
          
            ,tmp.Length))


          
          
             86
          
          
            return
          
          
            null
          
          
            ;


          
          
             87
          
          
             88
          
                   tagType = (
          
            byte
          
          )(tmp[
          
            0
          
          ] & 
          
            0x1f
          
          
            );


          
          
             89
          
          
            switch
          
          
             (tagType)


          
          
             90
          
          
                    {


          
          
             91
          
          
            case
          
          
            8
          
          
             :


          
          
             92
          
                       flvCtx.soundFormat = (
          
            byte
          
          )((tmp[FLV_TAG_HEADER_SIZE] & 
          
            0xf0
          
          ) >> 
          
            4
          
          
            ) ;


          
          
             93
          
                       flvCtx.soundRate   = (
          
            byte
          
          )((tmp[FLV_TAG_HEADER_SIZE] & 
          
            0x0c
          
          ) >> 
          
            2
          
          
            ) ;


          
          
             94
          
                       flvCtx.soundSize   = (
          
            byte
          
          )((tmp[FLV_TAG_HEADER_SIZE] & 
          
            0x02
          
          ) >> 
          
            1
          
          
            ) ;


          
          
             95
          
                       flvCtx.soundType   = (
          
            byte
          
          )((tmp[FLV_TAG_HEADER_SIZE] & 
          
            0x01
          
          ) >> 
          
            0
          
          
            ) ;


          
          
             96
          
                       hasAudioParams = 
          
            true
          
          
            ;


          
          
             97
          
          
            break
          
          
            ;


          
          
             98
          
          
            case
          
          
            9
          
          
             :


          
          
             99
          
                       flvCtx.videoCodecID = (
          
            byte
          
          )((tmp[FLV_TAG_HEADER_SIZE] & 
          
            0x0f
          
          
            ));


          
          
            100
          
                       hasVideoParams = 
          
            true
          
          
            ;


          
          
            101
          
          
            break
          
          
            ;


          
          
            102
          
          
            default
          
          
             :


          
          
            103
          
          
            break
          
          
            ;


          
          
            104
          
          
                    }


          
          
            105
          
          
            106
          
                   dataSize = FromInt24StringBe(tmp[
          
            1
          
          ],tmp[
          
            2
          
          ],tmp[
          
            3
          
          
            ]);


          
          
            107
          
                   skipSize = dataSize - 
          
            1
          
           + 
          
            4
          
          
            ;


          
          
            108
          
          
                }


          
          
            109
          
          
            110
          
          
            return
          
          
             flvCtx;


          
          
            111
          
          
            }


          
          
            112
          
          
            113
          
          
            int
          
           FromInt24StringBe(
          
            byte
          
           b0, 
          
            byte
          
           b1, 
          
            byte
          
          
             b2)


          
          
            114
          
          
            {


          
          
            115
          
          
            return
          
           (
          
            int
          
          )((b0<<
          
            16
          
          ) | (b1<<
          
            8
          
          ) |
          
             (b2));


          
          
            116
          
          
            }


          
          
            117
          
          
            118
          
          
            int
          
           GetTimestamp(
          
            byte
          
           b0, 
          
            byte
          
           b1, 
          
            byte
          
           b2, 
          
            byte
          
          
             b3)


          
          
            119
          
          
            {


          
          
            120
          
          
            return
          
           ((b3<<
          
            24
          
          ) | (b0<<
          
            16
          
          ) | (b1<<
          
            8
          
          ) |
          
                (b2));


          
          
            121
          
          
            }


          
          
            122
          
          
            123
          
          
            void
          
           SetTimestamp(
          
            byte
          
          [] data, 
          
            int
          
           idx, 
          
            int
          
          
             newTimestamp)


          
          
            124
          
          
            {


          
          
            125
          
               data[idx + 
          
            3
          
          ] = (
          
            byte
          
          )(newTimestamp>>
          
            24
          
          
            );


          
          
            126
          
               data[idx + 
          
            0
          
          ] = (
          
            byte
          
          )(newTimestamp>>
          
            16
          
          
            );


          
          
            127
          
               data[idx + 
          
            1
          
          ] = (
          
            byte
          
          )(newTimestamp>>
          
            8
          
          
            );


          
          
            128
          
               data[idx + 
          
            2
          
          ] = (
          
            byte
          
          
            )(newTimestamp);


          
          
            129
          
          
            }


          
          
            130
          
          
            131
          
          
            int
          
           Merge(FileStream fsInput, FileStream fsMerge, 
          
            bool
          
           isFirstFile, 
          
            int
          
           lastTimestamp = 
          
            0
          
          
            )


          
          
            132
          
          
            {


          
          
            133
          
          
            int
          
          
             readLen;


          
          
            134
          
          
            int
          
           curTimestamp  = 
          
            0
          
          
            ;


          
          
            135
          
          
            int
          
           newTimestamp = 
          
            0
          
          
            ;


          
          
            136
          
          
            int
          
          
             dataSize;


          
          
            137
          
          
            byte
          
          [] tmp = 
          
            new
          
          
            byte
          
          [
          
            20
          
          
            ];


          
          
            138
          
          
            byte
          
          [] buf = 
          
            new
          
          
            byte
          
          
            [MAX_DATA_SIZE];


          
          
            139
          
          
            140
          
               fsInput.Position = 
          
            0
          
          
            ;


          
          
            141
          
          
            if
          
          
             (isFirstFile)


          
          
            142
          
          
                {


          
          
            143
          
          
            if
          
          (FLV_HEADER_SIZE+
          
            4
          
           == (fsInput.Read(tmp,
          
            0
          
          ,FLV_HEADER_SIZE+
          
            4
          
          
            )))


          
          
            144
          
          
                    {


          
          
            145
          
                       fsMerge.Position = 
          
            0
          
          
            ;


          
          
            146
          
                       fsMerge.Write(tmp,
          
            0
          
          ,FLV_HEADER_SIZE+
          
            4
          
          
            );


          
          
            147
          
          
                    }


          
          
            148
          
          
                }


          
          
            149
          
          
            else
          
          
            150
          
          
                {


          
          
            151
          
                   fsInput.Position = FLV_HEADER_SIZE + 
          
            4
          
          
            ;


          
          
            152
          
          
                }


          
          
            153
          
          
            154
          
          
            while
          
          (fsInput.Read(tmp, 
          
            0
          
          , FLV_TAG_HEADER_SIZE) > 
          
            0
          
          
            )


          
          
            155
          
          
                {


          
          
            156
          
                    dataSize = FromInt24StringBe(tmp[
          
            1
          
          ],tmp[
          
            2
          
          ],tmp[
          
            3
          
          
            ]);


          
          
            157
          
                    curTimestamp = GetTimestamp(tmp[
          
            4
          
          ],tmp[
          
            5
          
          ],tmp[
          
            6
          
          ],tmp[
          
            7
          
          
            ]);


          
          
            158
          
                    newTimestamp = curTimestamp +
          
             lastTimestamp;


          
          
            159
          
                    SetTimestamp(tmp,
          
            4
          
          
            , newTimestamp);


          
          
            160
          
                    fsMerge.Write(tmp,
          
            0
          
          
            ,FLV_TAG_HEADER_SIZE);


          
          
            161
          
          
            162
          
                    readLen = dataSize+
          
            4
          
          
            ;


          
          
            163
          
          
            if
          
           (fsInput.Read(buf,
          
            0
          
          ,readLen) > 
          
            0
          
          
            ) {


          
          
            164
          
                           fsMerge.Write(buf, 
          
            0
          
          
            , readLen);


          
          
            165
          
                       } 
          
            else
          
          
             {


          
          
            166
          
          
            goto
          
          
             failed;


          
          
            167
          
          
                    }


          
          
            168
          
          
                }


          
          
            169
          
          
            170
          
          
            return
          
          
             newTimestamp;


          
          
            171
          
          
            172
          
          
                failed:


          
          
            173
          
          
            throw
          
          
            new
          
           Exception(
          
            "
          
          
            Merge Failed
          
          
            "
          
          
            );


          
          
            174
          
           }
        

?

測試通過,合并速度很快 !

?

不過,這個方法有一個缺點:沒有將各個文件里的關鍵幀信息合并,這個關鍵幀信息,切分 flv 文件時很重要,合并時就沒那么重要了。如果確實需要的話,可以用? flvtool2 來處理。

?

C# 版 flvmerge:快速合并多個flv文件


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 神马我我不卡伦影视 | 国产精品视频久久久久久 | 亚洲18岁禁止 | 欧美日韩在线观看视频 | 人人澡 人人澡 人人看欧美 | 亚洲欧洲国产成人精品 | 伊人亚洲 | 成人在线免费观看视频 | 视频一区二区在线 | 四虎地址8848jia| 爱爱爱免费视频 | 天天操91 | 亚色视频在线观看 | 最近更新在线中文字幕一页 | 国产精品视频第一区二区三区 | 99久久免费国产精品m9 | 久久99久久99精品免观看动漫 | 久草在线中文 | 国产精品久久亚洲不卡4k岛国 | 国产成人精品日本 | 久久综合国产 | 福利视频午夜 | 精品国产品香蕉在线观看 | 一 级做人爱全视频在线看 一a级毛片 | 亚洲成人在线视频 | 亚洲精品无码不卡在线播放he | 四虎影院海外永久 | 四只虎免费永久观看地址 | 久久伊人影院 | 国产欧美成人免费观看视频 | 亚洲精品成人一区二区 | 91福利在线看 | 国产精品第三页在线看 | 国产麻豆精品手机在线观看 | 天天操天天干天天射 | 亚洲欧美色综合大色 | 九九在线偷拍视频在线播放 | 波多野结衣精品一区二区三区 | 香蕉视频一级片 | 日韩一级欧美一级一级国产 | 欧美成人一区二免费视频 |