2015-09-06 1 views
1

На моем сайте пользователи могут загружать видео, которые зашифровываются «на лету» и хранятся на другом сервере. Я хочу сохранить видео битрейт, частоту кадров и т.д., но я не имею прямой доступ к ним, и я не могу просто использовать следующую команду:ffprobe - получение видеоинформации из файла chunk

ffprobe -show_streams -i file.mp4 

Я пытался экономить последний кусок на моем сервере, которые содержат атом Moov , но ffprobe выводит:

Format mov,mp4,m4a,3gp,3g2,mj2 detected only with low score of 1, misdetection possible! 
moov atom not found 
C:\file.mp4: Invalid data found when processing input 

Я проверил и усечение по крайней мере один байты причины этого, хотя атом Moov цел.

Каков правильный способ получения метаданных видео из фрагмента файла, содержащего атом атома? Как насчет получения информации от куска mdata atom?

ответ

6

Я не думаю, что парсер ffmpeg знает, как найти атом moov в chunked-файлах. Он анализирует (считывает или пропускает) кусок mp4-файлов куском до тех пор, пока не найдет атом moov, и если вы отрезаете часть начала, структура блока разрушена и, следовательно, не найдет атом moov.

Одним из возможных решений для вас является обнаружение файлов с атомом moov в конце и перемещение атома moov в начало с помощью ремуксации с помощью ffmpeg с помощью -movflags + faststart (или сопоставимых AVOptions в коде c/C++) , Затем вы можете обрезать файл после атома moov и разбор заголовка все равно будет работать.

[править]

Таким образом, в случае написания усеченного фрагмента известен изменения в мах демультиплексора (см комментариев), вот как вы бы. Прежде всего, постарайтесь не изменять mov_read_default(), это центральный механизм рекурсии, и любые изменения здесь, скорее всего, нарушат самые обычные функции. Скорее, вносите изменения в mov_read_header() (так как вы только заботитесь о синтаксисе заголовка здесь, а не о демультиплексировании фреймов). Вы найдете этот код:

if (mov->moov_retry) 
    avio_seek(pb, 0, SEEK_SET); 
if ((err = mov_read_default(mov, pb, atom)) < 0) { 
    av_log(s, AV_LOG_ERROR, "error reading header\n"); 
    mov_read_close(s); 
    return err; 
} 
} while (pb->seekable && !mov->found_moov && !mov->moov_retry++); 
if (!mov->found_moov) { 

Это пытается расшифровать структуру заголовка дерева, где Moov является верхним уровнем атома. В файле, он ищет последовательности, как это:

$ hexdump -n 32 -s 41934133 -C somefile.mov 
027fdd35 00 00 3e b4 6d 6f 6f 76 00 00 00 6c 6d 76 68 64 |..>.moov...lmvhd| 
027fdd45 00 00 00 00 c9 6b 7b f5 c9 6b 7c 02 00 00 02 58 |.....k{..k|....X| 

0x00003eb4 является размер в байтах «Moov» атома, и в том, что это subatom называется «mvhd» из размера 0x0000006c байт (структура дерева продолжается некоторое время после этого). Если установить указатель файла на это точное смещение, когда демультиплексирование файл, он будет декодировать правильно:

$ tail -c +41934134 somefile.mov > /tmp/hdr.mov 
$ ffprobe /tmp/hdr.mov 
[..] 
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f871b002a00] stream 0, offset 0x3f3e: partial file 
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f871b002a00] Could not find codec parameters for stream 0 (Video: h264 (avc1/0x31637661), none(bt709), 1280x720, 10695 kb/s): unspecified pixel format 
[..] 
    Stream #0:0(und): Video: h264 (avc1/0x31637661), none(bt709), 1280x720, 10695 kb/s, 29.97 fps, 29.97 tbr, 600 tbn, 1200 tbc (default) 
[..] 
    Stream #0:1(und): Audio: aac (LC) (mp4a/0x6134706D), 44100 Hz, mono, fltp, 63 kb/s (default) 

Как получить смещение файла в этот момент до вас:

  • вы можете добавить некоторый код до mov_read_header(), чтобы отсканировать файл для 'moov' (0x6d6f6f76) и установить указатель файла на 4 байта до этого
  • вы можете в своем коде, который создает этот фрагмент, сканировать moov и отрубать ведущий мусор раньше атом moov, прежде чем сохранять этот фрагмент в файл

Если вы собираетесь изменить ffmpeg и поместить это в версию ffmpeg, которую вы используете для других функций, я бы рекомендовал вам поставить ее под какую-то опцию, чтобы она не была включена для чтения файлов по умолчанию. В противном случае вы рискуете, что регулярный синтаксический анализ файла mov/mp4 больше не будет работать.

+0

Если бы я мог использовать ffmpeg для всего файла, я бы не стал задавать вопрос. –

+0

Если у вас никогда не было всего файла на диске, я не думаю, что ffmpeg может вам помочь. Вы можете попробовать mplayer на своем последнем фрагменте, хотя я сомневаюсь, что он сделает лучшую работу. Кроме того, вы можете написать собственный анализатор заголовков, используя соответствующий код из демпфера ffmpeg. (У меня было впечатление, что сервер будет иметь доступ к незашифрованному файлу, так как у вас есть доступ к последнему фрагменту.) –

+0

На самом деле, подумав об этом, вы даже можете добавить дополнительный «демон demo-файлов moov», который игнорирует куски и просто сканирует для атома moov и использовать существующий код разбора moov в ffmpeg, вызываемый из демультиплексора moov-фрагмента. Затем зарегистрируйте это как демпфер ffmpeg. Таким образом, у вас есть минимальный код для записи. Я могу дать несколько советов, если вы заинтересованы в таком подходе. –