LINUX.ORG.RU

Как на python вытащить метаданные потокового видео с помощью ffmpeg и subprocess

 , , , ,


0

0

Задача, есть поток в формате http://xxx.xxx.xxx.xxx:4022//udp/xxx.xxx.xxx.xxx:5239 это трансляция канала в потоке есть название канала «service_name: XXXXXXX» и «Program 10» нужно их получить в переменные.

В терминале ввожу: ffmpeg -i http://xxx.xxx.xxx.xxx:4022//udp/xxx.xxx.xxx.xxx:xxxx

Input #0, mpegts, from 'http://xxx.xxx.xxx.xxx:4022//udp/xxx.xxx.xxx.xxx:xxxx':
  Duration: N/A, start: 18527.576689, bitrate: N/A
  Program 10 
    Metadata:
      service_name    : xxxxxxxx
      service_provider: 
    Stream #0:0[0x3fb]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(top first), 720x576 [SAR 16:11 DAR 20:11], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x455](rus): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 192 kb/s

Как это получить на python3? С помощью «subprocess» и «ffmpeg»

Делаю для теста так:

import subprocess

url = 'http://xxx.xxx.xxx.xxx:4022//udp/xxx.xxx.xxx.xxx:xxxx'
cmds = ['ffmpeg', '-i', url]
data = subprocess.Popen(cmds)
print(data)

Выводится куча инфы, а хочется получить более конкретный вывод для разбора. Пример полного вывода:

Получаю ответ:
ffmpeg version 3.4.4-0ubuntu0.18.04.1 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.3.0-16ubuntu3)
  configuration: --prefix=/usr --extra-version=0ubuntu0.18.04.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100
  libavdevice    57. 10.100 / 57. 10.100
  libavfilter     6.107.100 /  6.107.100
  libavresample   3.  7.  0 /  3.  7.  0
  libswscale      4.  8.100 /  4.  8.100
  libswresample   2.  9.100 /  2.  9.100
  libpostproc    54.  7.100 / 54.  7.100
[h264 @ 0x55fda088b6a0] SPS unavailable in decode_picture_timing
[h264 @ 0x55fda088b6a0] non-existing PPS 0 referenced
[h264 @ 0x55fda088b6a0] SPS unavailable in decode_picture_timing
[h264 @ 0x55fda088b6a0] non-existing PPS 0 referenced
[h264 @ 0x55fda088b6a0] decode_slice_header error
[h264 @ 0x55fda088b6a0] no frame!
Input #0, mpegts, from 'http://xxx.xxx.xxx.xxx:4022//udp/xxx.xxx.xxx.xxx:xxx':
  Duration: N/A, start: 21251.384689, bitrate: N/A
  Program 10 
    Metadata:
      service_name    : xxxxxxxxx
      service_provider: 
    Stream #0:0[0x3fb]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(top first), 720x576 [SAR 16:11 DAR 20:11], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x455](rus): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 192 kb/s



Последнее исправление: Alecsandr1980 (всего исправлений: 3)

По современному, так, https://docs.python.org/3/library/asyncio-subprocess.html

import asyncio


URL = '...'


async def ffmpeg(cmd):
    proc = await asyncio.create_subprocess_shell(
        cmd,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

    stdout, stderr = await proc.communicate()

    print(f'[{cmd!r} exited with {proc.returncode}]')
    if stdout:
        print(f'[stdout]\n{stdout.decode()}')
    if stderr:
        print(f'[stderr]\n{stderr.decode()}')

asyncio.run(ffmpeg(f'ffmpeg -i {URL}'))

Что именно надо вытянуть из вывода?

vvn_black ★★★★★
()
Ответ на: комментарий от vvn_black

Спасибо, буду пробовать.

Что именно надо вытянуть из вывода?

Нужно получить эти данные № канала («Program XXX» ) и название канала («service_name:XXXXXX»)

Program XXX 
    Metadata:
      service_name:XXXXXX

Alecsandr1980
() автор топика
Ответ на: комментарий от tiandrey

Понты.

У ТСа вопрос с предысторией, я так понимаю, ему надо работать с целым плейлистом. Так что, почему бы не асинхронно это делать?

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от Alecsandr1980

ffprobe gathers information from multimedia streams and prints it in human- and machine-readable fashion.

Jopich1
()

Добавь -print_format json в параметры ffmpeg, вывод передаешь в json.load и получишь нормальный словарь.

hippi90 ★★★★★
()
Ответ на: комментарий от vvn_black

Да вы правы, у меня есть история... Вернее есть желание решить поставленную задачу. Она в следующем: найти у оператора udpyx серверы, далее просканировать из старого плейлиста возможный диапазон ip адресов на присутствие каналов IPTV (понимая диапозон адресов) и сохранения в плейлист с названием каналов и id для возможности добавления программы передач по ID канала. Я не скрываю , то что хочу реализовать. Я хочу этого добиться на финише...

Чего добился сейчас: 1 - Распознаю udpyx сервера по всем доступным IP провайдера (40 процессов сканирования, регулируется переменной) 10-15 секунд и 16 000 - 18 000 сканируется и выводится результат. 2 - Зная udpyx сервер и найдя клиентов подключенных к серверу сканирую диапазон ip адресов на присутствие канала. 3 - Полученный результат сохраняю в свой плейлист.

Что не решил: 1 - Пока это два скрипта... 2 - При сканировании канала не могу быстро и нормальным способом получить имя канала и id канала. Вся информация есть в потоке (VLC плеер видит в информации, название канала и номер канала в трансляции оператора...)

Я новичок, изучаю python пару месяцев, я ламер, гоблин мне все равно кто и как меня назовет. Но у меня есть цель. Я не преследую коммерческую цель, пишу для себя (ваше право не верить). Если что-то получится выложу. Пока учусь, код сырой (говнакод) без графического интерфеса. Переписывал уже несколько раз и думаю что буду еще переписывать. Асинхронное программирование для меня еще новинка, но пробовал многопоточность и многозадачность. Многозадачность для сканирования udpyx сервера подходить очень хорошо, но для сканирования каналов нет, так как многие операторы не дают возможность сделать более 4-6 а то и 1 соединения одновременно с одного ip ... Наверняка есть решение. Новые вопросы возникают на каждом этапе, я новичок и в IPTV и в программировании.

Если Вы можете и есть желание помочь, буду очень благодарен. Я и пушу в надежде что помогут и направят на решения, а если и с примером то ...)))

Alecsandr1980
() автор топика
Ответ на: комментарий от hippi90

Спасибо! Если несложно, покажите пример... Смысл понимаю с реализацией проблема. Формат json имел возможность оценить и мне он очень понравился. Писал скрипт где все настройки сохранял в json формате при старте загружал и отображал в граф интерфейсе на pyqt5, очень удобно. Небольшой опыт был. Я новичок в python и программировании (

Alecsandr1980
() автор топика
Ответ на: комментарий от tiandrey

Если честно, я думал что без поиска в строке и регулярных выражений не обойтись. Вы написали:

можно просто по префиксам строчки отбирать

я не знаю как это сделать, подскажите если несложно. Я учусь ))) Для меня многие вещи в новинку. Это может кому-то показаться простым, но я не понимаю как это сделать.

Alecsandr1980
() автор топика
Ответ на: комментарий от Alecsandr1980

Да вы правы, у меня есть история...
найти у оператора udpyx серверы, далее просканировать из старого плейлиста возможный диапазон ip адресов на присутствие каналов IPTV (понимая диапозон адресов) и сохранения в плейлист с названием каналов и id для возможности добавления программы передач по ID канала.
Я не скрываю , то что хочу реализовать. Я хочу этого добиться на финише...

1 - Распознаю udpyx сервера по всем доступным IP провайдера (40 процессов сканирования, регулируется переменной) 10-15 секунд и 16 000 - 18 000 сканируется и выводится результат. 2 - Зная udpyx сервер и найдя клиентов подключенных к серверу сканирую диапазон ip адресов на присутствие канала. 3 - Полученный результат сохраняю в свой плейлист.

Простите, а эти действия законны в РФ? А то тут просто форум находится в юрисдикции этого государства.

anonymous
()
Ответ на: комментарий от anonymous

вероятно законность будет определяться ответом на вопрос - извлечёт ли ТС коммерческую выгоду со своего поделия? потоки-то не шифрованы, т.е. никакой особой тайны он не вскрывает.

zad1ra
()
Ответ на: комментарий от zad1ra

Лицезрея потоки в влц, а очевидно для этого делается, и не оплачивая это лицезрение, что в этом случае?

anonymous
()
Ответ на: комментарий от zad1ra

вероятно законность будет определяться ответом на вопрос - извлечёт ли ТС коммерческую выгоду со своего поделия? потоки-то не шифрованы, т.е. никакой особой тайны он не вскрывает

Совершенно верно.

Alecsandr1980
() автор топика
Ответ на: комментарий от anonymous

Лицезрея потоки в влц, а очевидно для этого делается, и не оплачивая это лицезрение, что в этом случае?

Зря вы так на меня напали.

Всем спасибо! Разберусь сам уже близок.

Тему можно закрывать. (

Alecsandr1980
() автор топика
Ответ на: комментарий от Alecsandr1980

Ну попробуй как-то так:

import json, subprocess

result = ''

proc = subprocess.Popen(<cmd_args>, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
ret = proc.wait()
if ret != 0:
	result = proc.stderr.read()
else:
	result = json.load(proc.stdout)
print(result)

hippi90 ★★★★★
()
Ответ на: комментарий от anonymous

зависит от лицензии, по которой правообладатель передает свой контент. Обычно ничего.

zad1ra
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.