[Обучалово]Пишем решение для скачивания видео с YouTube одной кнопкой (часть 2)

Это чисто образовательный пост, целью которого будет изучение JavaScript и NodeJS.

Данный пост будет продолжением поста, где мы писали своё собственное решение для скачивания видео с YouTube при помощи yt-dlp одной кнопкой! Это важно!

Один коммент в обсуждении этого поста меня очень сильно затронул:

[Обучалово]Пишем решение для скачивания видео с YouTube одной кнопкой (часть 2)

Прочитав этот комментарий, я неделями не смогла нормально спать. Я всё представляла как Sedi сейчас сидит перед монитором, записывая ролики с Яндекс озвучкой на свой телефон.
Вы посмотрите на его аватару. Как же он страдает из-за этого! :

Держись, Sedi, помощь близко
Держись, Sedi, помощь близко

Мы доработаем наш код из первой части: сделаем чтобы видео гарантировано скачивались, добавим возможность загружать плейлисты, а также добавим возможность скачивать видео с VOT(voice over translation) озвучкой Яндекса. Затрону тонкости работы yt-dlp про которые мне многие писали.

Для работы с VOT будем использовать библиотеку

Та самая либа, которая используется для VOT Яндекса в браузерах отличных от Яндекс Браузера.

Кстати Вы не задумывались что скачивание видео с YouTube не разрешено и нарушает правила платформы и законы об авторском праве? А вот Яндекс как-то скачивает видео для своей нейроозвучки. У меня смутные сомнения что Яндекс договорился со всеми авторами на платформе. Получается главная фишка Яндекс Браузера...

Подумойте на досуге

Ну или они ничего не скачивают, а с колонки по звуку переводят. Не будем плохо думать про Яндекс.

Чтобы не было правовых вопросов ко мне, давайте Вы пообещаете, что у Вас есть Яндекс Браузер и этот скрипт для скачивания VOT Вы будете использовать только для возможности объединения видео с VOT.
А также что Вы будете договариваться с авторами каналов за право скачать видео.

Мы уважаем авторское право!

Спонсорский блок

Данный пост был создан только благодаря моим спонсорам. Спасибо, Карасик. На твои 120р донатов, я купила себе хлебушек! Кормилец ты, б..я..ь, мой!

1. Ошибки при работе с yt-dlp

1.1. Многие при использовании yt-dlp не прописывают параметр кукисов со своим браузером. Из-за чего он не работает с NSFW видео.

Решается прописыванием параметра с именем браузера

--cookies-from-browser firefox

Опытным путем установлено что кукисы нормально подцепляются только с Firefox.
Если для Вас Firefox неосновной браузер: установите Firefox, зайдите в свою учётку Гугла, откройте на Youtube любое NSFW видео, закройте навсегда Firefox.
Это наиболее простой вариант, если не хотите кукисы в виде текстового файла передавать - вариант для извращенцев.

1.2. Попытка скачивания часто завершается ошибкой "Read timed out"

Связано это с "замедлением" или "устареванием серверов" я не стала разбираться. Я очень ленивая.
Связано это с "замедлением" или "устареванием серверов" я не стала разбираться. Я очень ленивая.

Решается тем, что мы пытаемся скачать видео в бесконечном цикле пока видео не будет скачано.
Обычно видео скачивается с первой-второй попытки.

while(true) { const cb = await (async () => { return new Promise(async (resolve, reject) => { ... ytDlpWrap .exec(ytDlpWrap_args) .on('youtubeDlEvent', (eventType, eventData) => { console.log(eventType, eventData, attempts_count); }) .on('error', (error) => { return reject(`download_video: ${error}`) }) .on('close', () => { return resolve(true) }); }); })().catch((error) => {console.error(error)}); if (cb) return resolve(true); }

1.3. При скачивании плейлистов(при передачи параметра list в url'e) Вы также будете получать "Read timed out" с прекращением работы программы.

Решается "ручным" получением всех url видео в плейлисте и скачиванием каждого видео по-отдельности.

const metadata = await ytDlpWrap.getVideoInfo([`https://www.youtube.com/watch?list=${query.playlist_id}`, '--flat-playlist', '--cookies-from-browser', cookies_from_browser, '--extractor-args', 'youtubetab:skip=authcheck']).catch((error) => { console.error(error) }); metadata.forEach((data) => { tasks.push(data.url) });

2. Скачиваем VOT Яндекса

Здесь по аналогии с yt-dlp мы пытаемся получить ссылку с сервисов Яндекса, пока они её не отдадут. Это может быть очень долгий процесс.

async function download_yandex_audio(yt_url, audio_filepath, request_language= null) { return new Promise(async (resolve, reject) => { let attempts_count = 0; let result; while (true) { try { .... result = await client.translateVideo(translate_video_params); if (result?.translated && result?.url) break; .... } catch (error) { console.error(error); await delay(60000); } } //while const audio_dl_response = await download_file(result.url, audio_filepath).catch((error) => { console.error(error) }) if (audio_dl_response) return resolve(true); else return reject('download_yandex_audio: !audio_dl_response'); }); //return new Promise }

3. Объединение видео с аудио

Когда мы скачали видео и VOT, то объединяем их при помощи FFmpeg.

async function merge_video_audio(video_fp, audio_fp, merged_fp) { return new Promise(async (resolve, reject) => { try { Ffmpeg() .input(video_fp) .input(audio_fp) .complexFilter([`[0:a]volume=${audio_original__volume_percent}[a0];[1:a]volume=${audio_yandex__volume_percent}[a1];[a0][a1]amix=inputs=2[a]`]) .outputOptions([`-map 0:v`]) .outputOptions([`-map [a]`]) .outputOptions([`-c:v copy`]) .output(merged_fp) .on('end', function () { return resolve(true); }) .on('error', function (error) { return reject(`merge_video_audio error: ${error}` ); }) .run(); } catch (error) { //console.error(error); reject(`merge video audio error: ${error}`); } }); }

Он в отличии от vot.js и yt-dlp ни с какими сервисами не работает: с ним никаких проблем нет.

Кто хороший мальчик? Кто хороший мальчик?

4. Как это все запустить?

4.1 Скачайте архив с моего "гитхаба", разархивируйте в директорию по Вашему выбору

4.2 Устанавлите NodeJS

4.3 Скачайте в папку "bin" бинарник yt-dlp.exe

4.4 Установите FFmpeg. Он нужен для объединения видео и аудио в один файл.

4.5. Создайте и запустите файл yt-dlp.reg для слияние с реестром

Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\yt-dlp] "URL Protocol"="" [HKEY_CLASSES_ROOT\yt-dlp\shell] [HKEY_CLASSES_ROOT\yt-dlp\shell\open] [HKEY_CLASSES_ROOT\yt-dlp\shell\open\command] @=\"D:\Program Files\nodejs\node.exe\" \"D:\Program Files\yt-dlp\yt-dlp.js\" \"%1\"

Предварительно заменив "D:\Program Files\nodejs\node.exe" и "D:\Program Files\yt-dlp\yt-dlp.js" на свои пути к бинарнику NodeJS и скрипту.
Это создаст новый "класс" yt-dlp в реестре Вашей ОС.

Убедитесь что протокол установился: Win+R => regedit => "Компьютер\HKEY_CLASSES_ROOT\yt-dlp\shell\open\command"
Убедитесь что протокол установился: Win+R => regedit => "Компьютер\HKEY_CLASSES_ROOT\yt-dlp\shell\open\command"

4.6 Установите Userscript из файла "user.js" в своём Яндекс Браузере

4.7 Установите модули нажав "install.bat"

4.8 В файле yt-dlp.js измените директорию для скачивания и другие параметры по желанию

const download_dir = Path.join('D:\\', 'downloads'); //директория для сохранения скачанных видео const yandex_oauth_api_token = null; //OAUTH-ключ Яндекса или null. Нужен для "живых" голосов в нейроозвучке const response_language = 'ru'; const audio_original__volume_percent = 0.3; //уровень громкости оригинального видео [0-1] const audio_yandex__volume_percent = 1; //уровень громкости яндекс озвучки [0-1] const cookies_from_browser = 'firefox'; //откуда брать кукисы. chrome не работает!
Сложно, да? А никто не говорил что будет легко
Сложно, да? А никто не говорил что будет легко

Пишите, если есть вопросы

89
5
5
3
2
1
1
78 комментариев