FFMPEG. Загружаем часть видео с YouTube

  • Tutorial

Иногда мы хотим поделиться с друзьями частью какого то видео на YouTube — время концентрации внимания в современной реальности снижено до предела, и если скидывать ссылку на ролик(даже с таймкодом начала) с комментарием «смотреть с 21:51 по 24:55» — велика вероятность, что видео просмотрено не будет.

Кроме того — куски видео могут потребоваться для монтажа своих роликов — и довольно неудобно скачивать ради нескольких секунд весь ролик и искать/вырезать нужную часть в программе для монтажа.

Как загружать часть видео YouTube при помощи ffmpeg — под катом

Получаем прямую ссылку


Часть реализации моего Telegram бота на Python:
Нам потребуется библиотека pytube.
Создаем объект класса YouTube, которому передаем нашу ссылку, передаем номер нужного потока и получаем прямую ссылку на видео/аудио

from pytube import YouTube
link = "ссылка на видео"
itag = номер_потока
url = YouTube(link).streams.get_by_itag(itag).url

Обратите внимание, что потоки 1080p и 480p не имеют аудиодорожки.


Далее — подаем ссылку на вход (-i) ffmpeg вместе с таймкодами начала (-ss) и конца (-to) в формате «hh:mm:ss.xx». Задаем аудио кодек, битрейт и "-avoid_negative_ts make_zero" для того чтобы избежать подвисания картинки в начале видео из за потери ключевых кадров.

ffmpeg загрузит видео с нужного момента — нам не нужно качать видео на компьютер и обрезать — мы сразу выкачиваем нужный кусок.

process_call_str = 'ffmpeg -ss {1} -to {2} -i "{0}"'\
                            '-acodec aac -b:a 192k -avoid_negative_ts make_zero "{3}"'
                            .format(str(url), str(ss), str(t), download_file_path)
status = subprocess.check_call(process_call_str, shell=True)

Потоки без аудио


А что же делать с потоками без аудио? FFMPEG выручит нас и здесь — он может принимать на вход несколько потоков и объединять их.

Получаем прямую ссылку на видеопоток (например 137 — 1080p) и на поток с аудио/видео — например 18 — 360p

url = YouTube(link).streams.get_by_itag(itag).url
aurl = YouTube(link).streams.get_by_itag(18).url

Далее начинается магия — подаем на вход оба потока и при помощи "-map" берем видео дорожку из первого потока и аудио дорожку из второго потока и объединяем- теперь загрузка и объединение потоков происходит с нужного места из двух источников.

process_call_str = 'ffmpeg -ss {2} -to {3} -i "{0}" -ss {2} -to {3} -i "{1}"' \
                            ' -acodec aac -b:a 192k -avoid_negative_ts ' \
                            'make_zero -map 0:v:0 -map 1:a:0 "{4}"' \
                            .format(str(url), str(aurl), str(ss), str(t), download_file_path)
status = subprocess.check_call(process_call_str, shell=True)

Заключение


Вообще ffmpeg довольно мощная штука, возможности которой несколько шире переконвертации видео/аудио из одного формата в другой и позволяет соптимизировать нагрузку на входящий канал, диск, процессорное время и оперативку.

При помощи ffmpeg в боте реализовано ускорение/замедление звука с тонокомпенсацией, сжатие в формат opus. Теперь вот и загрузка видео/аудио с нужного момента по таймкодам — достаточно прикрепить к ссылке таймкоды и бот оперативно пришлет нужный кусок аудио/видео в нужном формате и качестве:

http://www.youtube.com/watch?v=Qgm36HHDEk0(30:29.5-30:38.5)
Поделиться публикацией
Похожие публикации
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 20
  • +1
    Спасибо, пригодится для одного из моих проектов!
    • +1
      Вообще ffmpeg довольно мощная штука

      Хочется добавить, что если вдруг нужно провести любые манипуляции в автоматическом режиме(скриптом, например) с видео и/или аудио файлом стоит посмотреть что там умеет ffmpeg.
      Ускорение/замедление/оверлей/объединение/разъединение/переконвертация, список возможностей очень обширный.
      • 0
        ага — я прямо прифигел что он умеет делать) до этого приходилось качать файл и на сервере уже с ними работать, а оказывается можно все делать одним инструментом, одной командой, при этом алгоритмы оптимизированные. Единственная сложность — скомпилировать ffmpeg может быть)
        • 0
          И даже для компиляции есть простой скрипт который умеет инклудить много проприетарных либ внутрь себя (раньше было особенно актуально для nvenc, ибо его не было ещё в коде родного ffmpeg'а). Разве что кофе на варит) Разработан кажется хабравчанином, только ник запамятовал. Вот ссылка (https://github.com/rdp/ffmpeg-windows-build-helpers), надеюсь не сочтут за рекламу.
      • +1
        Это (и многое другое) умеет youtube-dl. Но самому написать, конечно, интереснее :)
        • 0
          Это просто прекрасно! Не могли бы вы зайти в ишью #622 (открыт с 2013 года) и рассказать там всем как именно youtube-dl всё сам умет, а то там всё тоже сводится к ffmpeg.
          • 0
            Обрезать видеофайл в произвольном формате — не задача youtube-dl. В этом же тикете приведён пример:

            ffmpeg -ss 3:59:10 -i $(youtube-dl -f 22 -g 'https://www.youtube.com/watch?v=mMZriSvaVP8') -t 3:06:40 -c copy react-spot.mp4

            То же самое делает автор статьи, только вместо youtube-dl пользуется какой-то питоновской библиотекой. Библиотека оказалась не очень очевидна из консоли, в отличие от youtube-dl, поэтому появилась целая статья на хабре с предложением читать xml и вызывать ffmpeg изнутри питоновского скрипта.
            • 0
              Статья называется «FFMPEG. Загружаем часть видео с YouTube». Она, в первую очередь, про ffmpeg, а не про как именно получить прямую ссылку на видео/аудио. Соответственно писать «Это (и многое другое) умеет youtube-dl.» не уточняя о чём речь — крайне некорректно.
              Да, про то что по ссылке всё сводится к ffmpeg я сразу написал, зачем было это повторять?
              • 0
                Если бы в подводке к кату было написано не «как загружать часть видео YouTube при помощи ffmpeg», а «как загружать видео с ютуба и как обрезать его при помощи ffmpeg», вопросов бы не было. Я прочитал статью только потому что подумал: «ого, ffmpeg уже и этому научился?»
              • 0
                ну не претендую на «целую статью на хабре»(который скатился и вынуждает уже не тратить время на «целые статьи»), но совет как я считаю довольно полезный будет тем, кто занимается проектами с видео/аудио.
                Youtube-dl штука полезная, но очень медленная в большинстве случаев и недостаточно гибкая — использовать в реальном проекте можно разве что для получения метаданных. Я в своем изначально пользовался pytube — она умеет и качать видео и on_progress callback есть и age_restricted обходит, ну и много чего для работы с youtube из кода — лично мне использовать вызовы консольных приложений без обертки не очень удобно
                • 0
                  Не-не-не, статья хорошая и полезная. Я, вот, узнал про библиотеку для питона. Она для немного другого — как вы пишете, всякие колбэки и метаданные, но почему бы и нет.
          • 0
            А возможно с помощью этого инструмента извлечь аудиопоток из стрима? Сейчас довольно много годных трансляций музыкальных идет на ютубе не прерывных.
            • 0
              да — можно, более того — можно задерживать аудио относительно видео, прокидывать из потока в поток и тд
              • 0
                Пока к сожалению, не получается создать экземпляр с подобным стримом
                >>> yt = YouTube('https://www.youtube.com/watch?v=pJvDIO5P4p0') 
                
                Traceback (most recent call last):
                  File "<stdin>", line 1, in <module>
                  File "C:\Python27\lib\site-packages\pytube\__main__.py", line 84, in __init__
                    self.prefetch_init()
                  File "C:\Python27\lib\site-packages\pytube\__main__.py", line 93, in prefetch_
                init
                    self.init()
                  File "C:\Python27\lib\site-packages\pytube\__main__.py", line 128, in init
                    mixins.apply_signature(self.player_config_args, fmt, self.js)
                  File "C:\Python27\lib\site-packages\pytube\mixins.py", line 31, in apply_signa
                ture
                    url = stream['url']
              • 0
                youtube-dl --extract-audio --audio-quality 0 --audio-format mp3 "https://www.youtube.com/watch?v=pJvDIO5P4p0"

                (опять же должен быть установлен ffmpeg т.к. youtube отдаёт webm или m4a, который конвертируется в mp3)
                • 0
                  спасибо, жаль кармы, нет плюс не поставить.
                  • 0
                    Это все хорошо, но мы говорим про live stream на ютубе так? Что потом с ним делать?
                • 0
                  Озадачился таким-же вопросом, в идеале хотелось бы реализовать ретрансляцию:
                  YouTube LIVE -> свой сервер -> что-то удобоваримое для chrome или плееров
                  • 0
                    я пока так выхожу из положения
                    youtube-dl -f 95 -g "https://www.youtube.com/watch?v=_4BE2wBVCv8" 

                    Это отдает нам плейлист который понимает уже аимп например. Но не понимает MPD (
                    • 0
                      А для видео наверно так, перевод в ts
                      ffmpeg -i $(youtube-dl -f -g ) -copy <file_name>.ts
                      А там видимо веб серверу его скармливать этот файл. Могу ошибаться

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

                  Самое читаемое