Como juntar arquivos flv?

0

Estou no meu terceiro dia tentando baixar um vídeo de 4 minutos. É um Flash FLV que é dividido em três partes, as duas primeiras são cerca de 5MB, a terceira tem cerca de 3MB.

Apenas a primeira parte tem cabeçalhos FLV normais, os dois seguintes têm apenas um FLV no início. Eu não recorri a tentar escrever algo, baixei e tentei algumas centenas de megas de software Windows que realmente não faz isso.

Como se constata que não há necessidade de baixar as partes do vídeo, você pode retirá-las do cache do seu navegador assim que tiver reproduzido uma vez. Eu tentei CamStudio para capturar o vídeo da tela como está sendo jogado, mas meu computador mais rápido não é rápido o suficiente.

Eu não posso fazer isso em tempo real. Eu gostaria de fazer isso no OpenBSD, mas tenho uma máquina inicializada no Windows porque não há Flash para o OpenBSD. Eu posso tocá-lo com o MPlayer (Windows ou OpenBSD), tentando fazer uma junção simples das partes usando o MEncoder produz um vídeo que pára na primeira divisão. Tentei FFmpeg também. Eu gostaria de convertê-lo para algo mais normal, como MP4 ou AVI.

A especificação 10.1 parece muito diferente de 10.0 (link para PDF)

Os três FLVs no visualizador de MC (imagem); o primeiro é bem diferente:

    
por Alan Corey 22.03.2016 / 16:40

2 respostas

0

Não é uma resposta completa, mas a FLVMeta e uma leitura parcial das especificações da Adobe estão começando a esclarecer as coisas. De um despejo completo do FLVMeta, as tags ou seções de dados são assim:

    --- 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

Assim, você poderia ler o cabeçalho em um arquivo, colocar todas as tags em um arquivo cada e, em seguida, reconstruir quantos arquivos de entrada em quantos arquivos de saída desejasse. Cada "tag" eu chamaria de bloco, mas é um pedaço de dados. Você não precisa manipulá-los em tempo real. Cada um tem um timestamp, você só precisa colocá-los juntos nessa ordem e não dividir uma tag entre os arquivos.

Eu gostaria que o FLVMeta tivesse uma saída mais útil para mover as coisas sob o controle do programa, como tabulação ou dados delimitados por vírgulas. Talvez até crie um banco de dados SQLite para cada projeto, coloque todas as tags de áudio em uma tabela, vídeo em outra, script em outra. Talvez eu faça isso ainda, já que é open source e no Github. Seria mais simples se flvs não fossem big-endian e eu estivesse em uma máquina little-endian. Todos os inteiros são big-endian, como em um Mac.

    
por 26.03.2016 / 00:49
0

Feito finalmente. Acabei usando um programa em C que escrevi para concatená-los, uma vez que resolvi o bug que o EOF no primeiro arquivo de entrada acabava sendo um FF ou -1 no arquivo de saída, o que impedia os players e conversores naquele ponto.

flvmeta ainda deu avisos na saída disso, mas eu consegui convertê-lo em um mp4 usando:

    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;
    }
    
por 27.03.2016 / 18:55