Вы наверняка уже сталкивались с сайтом для скачивания видео с YouTube, в этой статье я покажу вам, как написать такой сайт, и пройдусь по концепциям и решениям, которые я использовал.
Прежде всего, давайте уточним, чего мы хотим добиться:
- предоставление ссылки на youtube для скачивания видео в формате mp4 или mp3 и предоставление обратной связи в реальном времени о статусе скачивания, чтобы это было круто.
Демо: https://youtube-downloader-app.netlify.app/
Код Api: https://github.com/MaurerKrisztian/youtube-downloader-api
Код пользовательского интерфейса: https://github.com/MaurerKrisztian/youtube-downloader-ui-vue
1. Как скачать видео с youtube?
После небольшого поиска, я нашел пару Linux cli инструментов, которые предназначены только для этого, большинство из них загружаются медленно, но к счастью я нашел ytb-dl, который каким-то образом обходит ограничение на загрузку.
2. Как взаимодействовать с cli API через Node.js?
В nodejs вы можете запускать команды cli с помощью встроенной функции spawn, которая создает дочерний процесс.
const downloadProcess = spawn('yt-dlp', [link]);
downloadProcess.stdout.on('data', (data) => {
console.log(data);
});
Ответы дочернего процесса на консоль, например, процент загрузки, скорость, размер… мы можем получать и обрабатывать эти данные с помощью stdout.on
3. Обертка CLI.
Я создал обертку вокруг yt-dlp, которая в основном параметризует вызовы и форматирует строки, извлеченные из std-otut, в формат json с парой regexps, чтобы я мог легко работать с этим в будущем.
События: Обертка выбрасывает 4 типа событий:
- start — когда начинается загрузка
- progress — информация о ходе загрузки (процент, скорость…)
- ошибка — если что-то пошло не так
- закрытие — если процесс завершился
Файл обертки: https://github.com/MaurerKrisztian/youtube-downloader-api/blob/main/src/cli-wrapper/yt-downloader-wrapper.ts
В результате, этот вызов функции может быть использован для начала загрузки событий броска из ответов cli в обрабатываемый формат:
process(link: string, id: string, path: string = './download', filename: string = "video", format: 'mp4' | 'mp3' = 'mp4') {...}
4. Управление событиями
В пользовательском интерфейсе целью будет обратная связь в реальном времени, поэтому решение REST API не подходит, но websocket подходит идеально, поэтому я создал сокетное соединение, клиент может запросить загрузку и подписаться на прогресс, ошибку, выполненный ответ, который отправляет информацию в реальном времени.
5. UI
Я пишу пользовательский интерфейс на Vue (мой первый проект на vue). По сути, он соединяется с сокетами бэкенда и отображает возвращенные данные.
6. Развертывание
Мы используем yt-dlp cli, поэтому env должен содержать это. Я смог развернуть его на своем собственном сервере, но я также пытался развернуть здесь https://railway.app/, но этот yt-dlp является «запрещенной зависимостью» из-за качества виртуального хостинга, но мы можем включить двоичный файл yt-dlp среди файлов и использовать его или удалить двоичный файл на лету. В настоящее время я работаю над этим.
*NOTE: это только mvp (есть что улучшать) в будущем я буду обновлять статью и проект, если вы найдете что улучшить, не стесняйтесь подать запрос на исправление или открыть проблему.