python ffmpeg moov atom не найден Неверные данные при обработке ввода - PullRequest
0 голосов
/ 02 мая 2018

У меня есть прогресс, который записывает экран и звук с микрофона, а затем объединяет видео и аудио запись (.mp4 и .wav) в один файл mkv.

Я использую python 3.6 и ffmpeg для достижения этой цели. Для коротких видеороликов (<20 секунд) это работает, но для более длинных записей выдается следующее сообщение об ошибке: </p>

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x55abb3a52540] moov atom not found
tmp/tmp_0.mp4: Invalid data found when processing input

Полный вывод:

ffmpeg version 3.3.7 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 7 (GCC)
configuration: --prefix=/usr --bindir=/usr/bin -- 
datadir=/usr/share/ffmpeg --docdir=/usr/share/doc/ffmpeg -- 
incdir=/usr/include/ffmpeg --libdir=/usr/lib64 --mandir=/usr/share/man -- 
arch=x86_64 --optflags='-O2 -g -pipe -Wall -Werror=format-security -Wp, 
-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp- 
buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat- 
hardened-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables' --extra- 
ldflags='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld ' -- 
extra-cflags='-I/usr/include/nvenc ' --enable-libopencore-amrnb -- 
enable- 
libopencore-amrwb --enable-libvo-amrwbenc --enable-version3 --enable-bzlib 
--disable-crystalhd --enable-fontconfig --enable-frei0r --enable-gcrypt -- 
enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable- 
libcdio --enable-indev=jack --enable-libfreetype --enable-libfribidi -- 
enable-libgsm --enable-libmp3lame --enable-nvenc --enable-openal --enable- 
opencl --enable-opengl --enable-libopenjpeg --enable-libopus --enable- 
libpulse --enable-libschroedinger --enable-libsoxr --enable-libspeex -- 
enable-libtheora --enable-libvorbis --enable-libv4l2 --enable- libvidstab - 
-enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid -- 
enable-avfilter --enable-avresample --enable-postproc --enable-pthreads -- 
disable-static --enable-shared --enable-gpl --disable-debug --disable- 
stripping --shlibdir=/usr/lib64 --enable-libmfx --enable-runtime-cpudetect
  libavutil      55. 58.100 / 55. 58.100
  libavcodec     57. 89.100 / 57. 89.100
  libavformat    57. 71.100 / 57. 71.100
  libavdevice    57.  6.100 / 57.  6.100
  libavfilter     6. 82.100 /  6. 82.100
  libavresample   3.  5.  0 /  3.  5.  0
  libswscale      4.  6.100 /  4.  6.100
  libswresample   2.  7.100 /  2.  7.100
  libpostproc    54.  5.100 / 54.  5.100
[wav @ 0x55abb3a0b880] Ignoring maximum wav data size, file may be invalid
[wav @ 0x55abb3a0b880] Estimating duration from bitrate, this may be 
inaccurate
Guessed Channel Layout for Input Stream #0.0 : stereo
Input #0, wav, from 'tmp/tmp_0.wav':
  Metadata:
    encoder         : Lavf57.71.100
  Duration: 00:00:21.97, bitrate: 768 kb/s
Stream #0:0: Audio: pcm_mulaw ([7][0][0][0] / 0x0007), 48000 Hz, 
stereo, s16, 768 kb/s
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x55abb3a52540] moov atom not found
tmp/tmp_0.mp4: Invalid data found when processing input

Файл Python (ffmpeg.py) выглядит следующим образом. Класс, AV_COMPILE, еще не завершен, задерживается вышеупомянутой ошибкой и поэтому все еще использует исходные тестовые файлы в качестве значений по умолчанию. Но в противном случае это должно сработать:

import os, time, glob

TMP_DIR = "tmp"
DISPLAY = os.environ['DISPLAY']
EXT = {
    'Video':'mp4',
    'Audio':'wav',
    'AV':'mkv',
}

class ffmpegVideo:

    FFMPEG_BIN = "ffmpeg"
    AUDIO = False

    def __init__(self, fps = 30, audio = True):
    global TMP_DIR, DISPLAY, EXT

    self.fps = fps

    if audio:
        self.AUDIO = True

    self.video_filename = self.unique_filename()

    self.command = [ self.FFMPEG_BIN,
        '-video_size', '1920x1080',
        '-framerate', str(fps),
        '-f', 'x11grab',
        '-i', DISPLAY,
        '-vcodec', 'libx264',
        '-qp', '0',
        '-preset', 'ultrafast',
        '-y', TMP_DIR + '/' + self.video_filename
    ]

def start(self):
    import threading as th

    thread = th.Thread(target=self.record)
    thread.start()

def record(self):
    import subprocess as sp

    self.pipe = sp.Popen(self.command, stderr=sp.PIPE)

    if self.AUDIO:
        ffmpegAudio().start()

def stop(self):
    self.pipe.terminate()

def unique_filename(self):
    global TMP_DIR, EXT

    i = 0

    while os.path.exists((TMP_DIR + '/' + 'tmp_%s.%s') % (i, EXT['Video'])):
        i += 1

    return ('tmp_%s.%s') % (i, EXT['Video'])

class ffmpegAudio:

    FFMPEG_BIN = "ffmpeg"

    def __init__(self):

        self.audio_filename = self.unique_filename()

        self.command = [ self.FFMPEG_BIN,
            '-f', 'pulse',
            '-ac', '2',
            '-ar', '48000',
            '-i', 'default',
           '-acodec', 'pcm_mulaw',
           '-y', TMP_DIR + '/' + self.audio_filename
        ]

    def start(self):
        import threading as th

        au_thread = th.Thread(target=self.record)
        au_thread.start()

    def record(self):
         import subprocess as sp

        self.pipe = sp.Popen(self.command, stderr=sp.PIPE)

    def stop(self):
        self.pipe.terminate()

    def unique_filename(self):
        global TMP_DIR, EXT

        i = 0

        while os.path.exists((TMP_DIR + '/' + 'tmp_%s.%s') % (i, EXT['Audio'])):
        i += 1

        return ('tmp_%s.%s') % (i, EXT['Audio'])

class AV_COMPILE:

    def __init__(self, au_in = TMP_DIR + '/' + 'out1.wav', vd_in = 
TMP_DIR + '/' + 'test4.mp4', out = TMP_DIR + '/' + 'av.mkv'):
        import subprocess as sp

        au_in = min(glob.iglob(TMP_DIR + '/*.wav'), key=os.path.getctime)
        vd_in = min(glob.iglob(TMP_DIR + '/*.mp4'), key=os.path.getctime)

        self.command = ('ffmpeg -i %s  -r 30 -i %s -shortest -c:a aac -c:v copy %s') % (au_in, vd_in, out)
        sp.call(self.command, shell=True)

Буду признателен за любую помощь, которую вы могли бы оказать, чтобы понять, почему это происходит и как устранить ошибку. Кроме того, я рад получить любые другие советы о том, как улучшить этот код, или о любых других проблемах, которые кто-либо может заметить.

EDIT: Теперь я считаю, что причина этой ошибки в более длинных и иногда более коротких видео заключается в том, что программа пытается попытаться скомпилировать вывод av независимо от того, завершила ли она компиляцию исходного видеофайла. Я протестировал функцию time.sleep(10) для задержки AV_COMPILE, и это, похоже, работает.

Однако, поскольку видеофайлы становятся больше, очевидно, что необходимо отрегулировать задержку. Поэтому я хотел бы знать, как я могу отдельно проверить целостность видеофайла и определить, безопасно ли переходить к следующему шагу.

1 Ответ

0 голосов
/ 11 мая 2018

Относительно moov atom not found хорошо, я проверил ваш файл, и атом есть, но на заднем плане вашего файла (но он должен быть доступен сначала, прежде чем остальные данные MP4 могут быть обработаны).

Контейнеры MP4 структурированы таким образом, что данные a / v хранятся без заголовков кадра, а атом Moov представляет собой таблицу, в которой перечислены позиции байтов и длины байтов для каждого кадра a / v. Атом Moov может существовать только после завершения записи, когда соответствующие метаданные теперь могут быть созданы для сохраненных данных.

Вот почему был представлен фрагментированный MP4.

Решение:

Не помещайте ваши аудио / видео данные в MP4, а затем переносите те же аудио / видео из MP4 в контейнер MKV. Я подозреваю, что вы использовали настройку контейнера MP4 для того, чтобы получить код (изображение), закодированный с помощью видеокодека H.264?

Я не использую Python, но попробуйте установить:

'Video':'libx264',
'Audio':'wav',
'AV':'mkv',
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...