Библиотека сайта rus-linux.net
Хакинг FFmpeg с помощью Python, часть вторая
Оригинал: Hack FFmpeg With Python, Part Two
Автор: SureSwift Content
Дата публикации: 23 февраля 2017 года
Перевод: А. Кривошей
Дата перевода: март 2018 г.
В первой части этого руководства мы рассмотрели некоторые простые примеры, в которых язык программирования python используется для взаимодействия с мультимедийным фреймворком с открытым исходным кодом FFmpeg.
Прежде чем получать вывод утилиты ffprobe, исследовать видео и превращать его в объект python, мы настоятельно рекомендуем вам взглянуть на словари python, которые используются для хранения информации в виде пар "значение - ключ".
{'website':'unixmen', 'language':'python'}
Приведенный выше объект в python называется словарем. Это тип dict. Запустите оболочку python, которую мы установили в предыдущей части, чтобы вам было легче понять этот процесс.
$ python2.7
После запуска интерпретатора присвойте значение этого словаря переменной:
d = {'website':'unixmen', 'language':'python'}
Вы можете легко получить информацию о типе объекта python с помощью следующей команды:
type(d)
Вы получите следующий вывод:
<type 'dict'>
Для доступа к значению из словая используется название ключа со следующим синтаксисом:
d['website']
Соответствующее значение выводится в консоли.
'unixmen'
Такой же подход для второго значения.
d['language'] 'python'
Основной причиной выбора такого объекта python является формат вывода, возвращаемого утилитой ffprobe. Словарь python позволяет очень просто хранить такую длинную строку.
Давайте более подробно рассмотрим пример из реального мира. Предположим, мы хотим получить всю информацию, хранящуюся между тегами [FORMAT], [/ FORMAT], и сохранить ее в словаре python, чтобы облегчить вывод данных. Модуль subprocess поможет нам создать процесс, как показано ниже:
import subprocess cmds = ['/usr/local/bin/ffprobe', '-show_format', 'test.mp4'] p = subprocess.Popen(cmds, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Метод communicate поможет получить вывод.
output, _ = p.communicate()
Затем мы выведем информацию с помощью оператора print:
print(output)
Вы увидите в консоли python что-то, похожее на эти строки.
[FORMAT] filename=test.mp4 nb_streams=2 nb_programs=0 format_name=mov,mp4,m4a,3gp,3g2,mj2 format_long_name=QuickTime / MOV start_time=0.000000 duration=263.012422 size=36004015 bit_rate=1095127 probe_score=100 TAG:major_brand=mp42 TAG:minor_version=0 TAG:compatible_brands=isommp42 TAG:creation_time=2016-08-11T03:35:58.000000Z [/FORMAT]
Как видно из приведенного выше примера, в выводе переменной сохраняется длинная строка. Работать с такой строкой очень сложно. Это идеальный случай, когда действительно полезным становится синтаксический анализ.
Таким образом, нам нужно построить простую функцию, которая будет получать длинную строку в качестве ввода, и возвращать словарь python со всей информацией. Следующий пример позволяет легко понять тип объекта, который мы планируем возвращать внутри функции, которая будет производить парсинг строки:
{'filename':'test.mp4', 'nb_streams':2, 'duration':263.012422}
Функция нам требуется для обработки парсинга строки. Python позволяет легко определить функцию с помощью оператора def.
def test(a): return a
Функция test очень проста. Она получает аргумент и возвращает его обратно.
Наша функция, которая будет заниматься парсингом информации о формате, будет называться parse_format. Ниже приведена основная идея о том, как должна быть сконструирована эта функция:
def parse_format(format_string): format_info = {} return format_info
Таким образом, идея функции заключается в том, что она берет строку в качестве ввода, создает пустой словарь, который будет использоваться для хранения данных, а затем просто возвращает словарь.
Посмотрев на длинную строку, возвращаемую при тестировании видео, мы найдем две строки, которые не являются данными, хранящимися внутри словаря format_info. Эти две строки являются тегами [FORMAT] и [/ FORMAT].
Оператор if может помочь проверить, присутствует ли какое-либо из этих строк в текущей строке, если это условие выполняется, мы их пропускаем и переходим к следующей строке.
Далее окончательный код нашей функции.
def parse_format(format_string): format_info = {} for line in format_string.split('\n'): if '=' in line: k, v = line.split('=') k = k.strip() v = v.strip() format_info[k] = v return format_info
Использование функции, которая занимается анализом информации, возвращаемой ffprobe, очень просто. Прежде чем использовать нашу функцию, необходимо создать новый процесс, как показано ниже:
cmds = ['/usr/local/bin/ffprobe', '-show_format', 'test.mp4'] format_p = subprocess.Popen(cmds, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
Затем используем метод communicate:
output, _ = format_p.communicate()
Давайте посмотрим, работает ли наша функция парсинга:
format_information = parse_format(output)
Если вы не увидели никаких ошибок, теперь мы можем вывести информацию с помощью оператора print:
print(format_information)
Вывод, отображаемый в консоли, должен выглядеть примерно так, как показано ниже. В зависимости от видеофайла, ваши ключи будут иметь разные значения.
{'nb_streams': '2', 'start_time': '0.000000', 'format_long_name': 'QuickTime / MOV', 'TAG:creation_time': '2016-08-11T03:35:58.000000Z', 'format_name': 'mov,mp4,m4a,3gp,3g2,mj2', 'filename': 'test.mp4', 'TAG:compatible_brands': 'isommp42', 'bit_rate': '1095127', 'nb_programs': '0', 'TAG:major_brand': 'mp42', 'duration': '263.012422', 'probe_score': '100', 'TAG:minor_version': '0', 'size': '36004015'}
Наличие всей информации о словаре python позволяет нам легко извлекать данные, такие как заголовок исследуемого видео, количество потоков, продолжительность в секундах, а также размер файла.
Например, чтобы получить заголовок видео, мы можем использовать следующий код.
format_information['filename']
Продолжительность видео можно извлечь из словаря с помощью следующего кода:
format_information['duration']
Аналогично получаем информацию о размере файла:
format_information['size']
Заключение
В этом руководстве мы рассмотрели процесс получения информации, используя модуль subprocess. В следующей части мы собираемся создать с нуля очень полезный скрипт, который будет автоматизировать некоторые из функций ffmpeg.