Скачиваем кусок видео с YouTube с помощью ffmpeg

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Я выступил с докладом на WordCamp US 2023 и захотел скачать видео с ним. Я всегда стараюсь хранить собственные копии таких видео, потому что некоторые конференции в прошлом со временем закрывали к ним доступ.

Моя презентация в прямом эфире транслировалась через YouTube, однако получившееся видео длится 9,5 часа!

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

Я нашёл этот рецепт пользователя StackExchange godofgrunts, который походил на то, что мне нужно:

#!/bin/bash
#Arguments: URL, Time stamp -5 seconds, length of clip, video file name
readarray -t urls <<< """ class="formula inline">1")"
ffmpeg -ss "" class="formula inline">{urls[0]}" -ss "" class="formula inline">{urls[1]}" -ss 5 -map 0:v -map 1:a -c:v libx264 -c:a aac -t " class="formula inline">4

Но когда я запустил его, то получил ошибку, потому что на моём Mac не было readarray.

Поэтому я вставил команды в GPT-4 со следующим промтом:

Port this to macOS - I do not have the readarray command

«Портируй это на macOS - у меня нет команды readarray»

Он выдал мне такое:

#!/bin/bash
# Arguments: URL, Time stamp -5 seconds, length of clip, video file name

IFS=$'\n' urls=($(yt-dlp --youtube-skip-dash-manifest -g "$1"))
ffmpeg -ss $2 -i "${urls[0]}" -ss $2 -i "${urls[1]}" -ss 5 -map 0:v -map 1:a -c:v libx264 -c:a aac -t $3 $4

1. Переменной IFS присвоен символ новой строки, чтобы возвращаемые yt-dlp URL разделялись по новым строкам.

2. Массив urls заполняется подстановкой команды и присвоением массива.

3. Остальная часть скрипта осталась неизменной.

Я сохранил команды как clip-youtube.sh, выполнил chmod 755 clip-youtube.sh и... это сработало!

Я вызвал код следующим образом:

./clip-youtube.sh 'https://www.youtube.com/watch?v=LpDulftMkew' 8:18:25 3600 simon-wordcamp.mp4

Моя часть видео начинается примерно с 8 ч 18 мин и 25 с. Я указал 3600, чтобы скачать час контента (раздел Q&A длился немного больше, нужно было указать большее значение).

Для выполнения скрипта потребовался почти целый час! В конечном итоге, возможно, было бы быстрее скачать файл целиком, а потом нарезать его.

Но... в результате я получил файл simon-wordcamp.mp4 на 308 МБ.

Как всё это работает

Немного объясню код. Первая часть выглядит так:

yt-dlp --youtube-skip-dash-manifest -g "$1"

Выполнив её, мы получим такой результат:

yt-dlp --youtube-skip-dash-manifest -g 'https://www.youtube.com/watch?v=LpDulftMkew'

Вывод:

https://rr2---sn-8xgp1vo-p5qs.googlevideo.com/videoplayback?expire=1693085635&ei=YxvqZJ2RJb6t_9EPwuSgkAk&ip=65.201.185.136&id=o-AAyFKyoRtQrnNL3zrfdNULpm39lectAVHkcbeoAF2jLI&itag=137&source=youtube&requiressl=yes&mh=Vv&mm=31%2C26&mn=sn-8xgp1vo-p5qs%2Csn-ab5l6nkd&ms=au%2Conr&mv=m&mvi=2&pcm2cms=yes&pl=21&initcwndbps=1816250&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=2674985800&dur=34334.996&lmt=1693003267530862&mt=1693063539&fvip=1&keepalive=yes&fexp=24007246&c=IOS&txp=7209224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AOq0QJ8wRAIgDzk4tc_9bCUvwN0Wg_73hJdAJHl2CDJW8ntEGmIu5HoCIH6u9T8EZSnITAln8Ebh6Vt_P17x3sKbecFfwdkH7AKP&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgFZ9mdd4hTdBnDCn0DhbbOkgCLsKQbaoI8eFU3SDBiAYCIHIwpPwy8LfmGv1sNezegCuIQ8f5OZV-J1pBYYZ6Spxi
https://rr2---sn-8xgp1vo-p5qs.googlevideo.com/videoplayback?expire=1693085635&ei=YxvqZMPFMYmi_9EP1YOsqA4&ip=65.201.185.136&id=o-AJrteXKDNXZVv-8ohwCNtkgRusvA7tjSCrK-Yhvj13FZ&itag=251&source=youtube&requiressl=yes&mh=Vv&mm=31%2C26&mn=sn-8xgp1vo-p5qs%2Csn-ab5sznzk&ms=au%2Conr&mv=m&mvi=2&pl=21&initcwndbps=1816250&spc=UWF9f2Mp7IK_PwGaM7XhKZtnkS6X3I4&vprv=1&svpuc=1&mime=audio%2Fwebm&gir=yes&clen=318551384&dur=34335.041&lmt=1693003946161041&mt=1693063539&fvip=1&keepalive=yes&fexp=24007246%2C51000023&beids=24350017&c=ANDROID&txp=7208224&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AOq0QJ8wRQIhAK--nt8-f1qPpaG1ioc5I2gQLEVD5sCFCUh6fjruOHPUAiAWz0o0kOhS-M--vPkNWD0ZqdSguD5lxFxwLu46Zgb5jw%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIgWmu0j9lq5uhkxVkOfUK4cctQbhgwMcU1stpCvLNYBB4CIQCMt0PzKQ5T9ofUxoIYywGN_fE72dMvPuoEvJZr4jOwJg%3D%3D

Я немного поискал и выяснил, что --youtube-skip-dash-manifest больше не нужен. То есть на самом деле команда будет такой:

yt-dlp -g 'https://www.youtube.com/watch?v=LpDulftMkew'

Опция -g заставляет yt-dlp создать URL стримов, а не скачивать видео.

Команда возвращает два URL, потому что один относится к видеопотоку, а другой — к аудиопотоку. Мы можем переформатировать эти URL, чтобы это стало очевиднее — подсказка заключается в том, что в первом случае используется &mime=video%2Fmp4 , а во втором — &mime=audio%2Fwebm.

Затем скрипт вызывает ffmpeg. Вот очищенная версия этого вызова:

ffmpeg \
  -ss '8:18:25' -i "${VIDEO_STREAM_URL}" \
  -ss '8:18:25' -i "${AUDIO_STREAM_URL}" \
  -ss 5 \
  -map 0:v \
  -map 1:a \
  -c:v libx264 \
  -c:a aac \
  -t 3600 simon-wordcamp.mp4

Две строки -ss выполняют поиск отметки 8:18:25 в видеопотоке и в аудиопотоке.

--s 5 выполняет поиск на 5 секунд внутрь скомбинированного вывода. В инструкциях на StackExchange говорится, что нужно начинать как минимум за 5 с до той части видео, которую вы хотите сохранить. В рецепте с StackExchange указано, что это нужно «для того, чтобы дать несколько секунд на поиск хорошего ключевого кадра».

-map 0:v и -map 1:a задают первый поток как видео, а второй — как аудио.

-c:v libx264 и -c:a aac конфигурируют выходные кодеки для видео (H.264) и аудио (AAC).

-t 3600 simon-wordcamp.mp4 задаёт длительность (час, или 60 * 60 секунд) и имя выходного файла.

Прим. пер.: вообще для решения задачи можно было использовать встроенную в yt-dlp функцию --download-sections, но текст всё равно интересен необычностью изложенной идеи.

Дополнительные ссылки

  • Exporting and editing a Twitter Spaces recording - 23.03.2022

  • Syncing slide images and audio in iMovie - 15.06.2023

  • Reading thermometer temperatures over time from a video - 02.04.2023

  • Trick Apple Photos into letting you access your video files - 12.04.2022

  • Running nanoGPT on a MacBook M2 to generate terrible Shakespeare - 01.02.2023

  • sips: Scriptable image processing system - 18.02.2023

  • Set a GIF to loop using ImageMagick - 03.08.2021

  • Rewriting a repo to contain the history of just specific files - 22.03.2022

  • Compiling to WASM with llvm on macOS - 28.03.2022

  • Using curl to run GraphQL queries from the command line - 21.02.2022

Источник: https://habr.com/ru/articles/757276/


Интересные статьи

Интересные статьи

Продолжаем знакомиться с концептуальным проектированием в архитектуре и осваивать технику прямого 3D-моделирования в Платформе nanoCAD.[КОА1] В первой статье, посвященного моделированию проекта «...
Один из самых гибких и привычных способов сгенерировать pdf — написать код на LaTeX и воспользоваться соответствующей программой. Но есть и другие способы, которые могут ...
Векторная графика очень удобна для иллюстраций. Молекулы состоят из атомов соединённых связями. Хочется, чтобы операции редактирования рисунка химической структуры осущес...
Видеореклама набирает все больше оборотов: пользователи лучше реагируют на видео, чем на статические картинки и баннеры, а рекламные системы постоянно увеличивают количес...
Что, если у вас идея для классного, полезного белка, и вы хотите получить его в реальности? Например, хотите создать вакцину против H. pylori (как словенская команда на iGEM 2008), создав гибридн...