如何合并分割的 flv 文件?

如何合并分割的 flv 文件?

这是我尝试下载一段 4 分钟的视频的第三天。这是一个 Flash FLV,分为三部分,前两部分约 5MB,第三部分约 3MB。

只有第一部分有正常的 FLV 标头,接下来的两部分开头大多只有一个 FLV。我没有尝试自己编写一些东西,只是下载并尝试了几百兆的垃圾 Windows 软件,但实际上并没有这样做。

事实证明,无需下载视频部分,播放完一次后即可将其从浏览器缓存中取出。我曾尝试使用 CamStudio 从屏幕上捕捉正在播放的视频,但我最快的电脑速度不够快。

我无法实时执行此操作。我想从 OpenBSD 执行此操作,但我有一台机器启动到 Windows,因为 OpenBSD 没有 Flash。我可以用 MPlayer(Windows 或 OpenBSD)播放它,尝试使用 MEncoder 对各部分进行简单的连接会产生在第一次分割处停止的视频。也试过 FFmpeg。我想将其转换为更普通的格式,例如 MP4 或 AVI。

10.1 规范与 10.0 有很大不同(PDF 热链接)

MC viewer 中的三个 FLV(图片);第一个完全不同:

关联

答案1

虽然还没有完整的答案,但 FLVMeta 和对 Adob​​e 规范的部分解读开始揭示一些问题。从 FLVMeta 完整转储来看,标签或数据部分如下所示:

    --- Tag #1019 at 0xCBEB5 (835253) ---
    Tag type: audio
    Body length: 213
    Timestamp: 124957
    * Sound type: stereo
    * Sound size: 16
    * Sound rate: 44
    * Sound format: AAC
    Previous tag size: 224
    --- Tag #1020 at 0xCBF99 (835481) ---
    Tag type: video
    Body length: 1201
    Timestamp: 124960
    * Video codec: AVC
    * Video frame type: inter frame
    Previous tag size: 1212
    --- Tag #1021 at 0xCC459 (836697) ---
    Tag type: audio
    Body length: 225
    Timestamp: 124980
    * Sound type: stereo
    * Sound size: 16
    * Sound rate: 44
    * Sound format: AAC
    Previous tag size: 236
    --- Tag #1022 at 0xCC549 (836937) ---
    Tag type: video
    Body length: 542
    Timestamp: 125000
    * Video codec: AVC
    * Video frame type: inter frame
    Previous tag size: 553

因此,您可以将标头读入一个文件,将所有标签分别放入 1 个文件中,然后将任意数量的输入文件重建为任意数量的输出文件。我将每个“标签”称为一个块,但它是一块数据。您不必实时操作它们。每个标签都有一个时间戳,您只需按该顺序将它们放在一起,不要将标签拆分到多个文件中。

我希望 FLVMeta 有更多有用的输出,以便在程序控制下移动制表符或逗号分隔的数据等内容。甚至可以为每个项目创建一个 SQLite 数据库,将所有音频标签放在一个表中,将视频放在另一个表中,将脚本放在另一个表中。也许我会这样做,因为它是开源的,而且在 Github 上。如果 flvs 不是大端的,而我在一台小端的机器上,那就更简单了。所有整数都是大端的,就像在 Mac 上一样。

答案2

终于完成了。我解决了第一个输入文件的 EOF 在输出文件中最终变成 FF 或 -1 的错误,从而停止了播放器和转换器,最后我使用我编写的 C 程序将它们连接起来。

flvmeta 仍然对此输出发出警告,但我能够使用以下命令将其转换为 mp4:

    ffmpeg -i out4.flv -vcodec copy -acodec copy out4.mp4


    /*
       My flv concat, a single-use program
    */

    #include <stdio.h>  // don't need most of these headers
    #include <stdlib.h>
    #include <string.h>
    #include <endian.h>  // FLVs have big endian values
    #include <unistd.h>
    #include <fcntl.h>
    #include <inttypes.h>

    FILE *opf;

    void docopy(char *fn, uint ofs) {
      FILE *ipf;
      unsigned char ch;
      ipf = fopen(fn,"r");
      if (ipf == NULL) {
        printf("Failed to open %s\n",fn);
        fclose(opf);
        exit(1);
      }
      fseek(ipf,ofs,SEEK_SET);  // jump to passed in offset
      while (!feof(ipf)) {  // not super efficient
        ch = fgetc(ipf);
      // this DOES have an effect, it stops the -1 from being written
        if (!feof(ipf))
          fputc(ch,opf);
      }
      printf("outfile now at %x\n",(unsigned int) ftell(opf));
      fclose(ipf);
    }

    void outhdr(void) { // write boilerplate flv header
      opf = fopen("out4.flv","w");
      if (opf == NULL) {
        printf("Error creating new output file.\n");
        exit(1);
      }
      fprintf(opf,"FLV%c%c%c%c%c%c",1,5,0,0,0,9); // audio and video enabled
      // This becomes the first PreviousTagSize:
      fprintf(opf,"%c%c%c%c",0,0,0,0);  // flvmeta seems to approve
    }

    int main(void) {
      outhdr();  // write a vanilla header
      docopy("media1.flv", 13);  // copy, starting at byte 13
      docopy("media2.flv", 13);
      docopy("media3.flv", 13);
      fclose(opf);
      return 0;
    }

相关内容