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

Это руководство предназначено для начинающих разработчиков, желающих познакомиться с Puppeteer.

Цель

Создайте RESTful API, который будет принимать два запроса (идентификатор видео YouTube и временную метку) и возвращать текст.

Примечание

Если вы предпочитаете альтернативу использованию Google Cloud Vision API для чтения текста, есть альтернативы с открытым исходным кодом, такие как Tesseract.js.

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

Ресурсы

Документация по API Puppeteer:
https://github.com/GoogleChrome/puppeteer/blob/v1.10.0/docs/api.md

Документация по Google Cloud Vision API:
https://cloud.google.com/vision/docs/

Другие руководства:
https://blog.georgi-yanev.com/projects/youtube-timestamp-screenshot/
https://codeburst.io/a-guide-to-automating- очистка-веб-с помощью-javascript-chrome-puppeteer-node-js-b18efb9e9921
https://timleland.com/headless-chrome-on-heroku/

Начиная

Примечание: мы будем использовать функцию async / await с Puppeteer, для чего потребуется Node v7.6.0 или выше.

Создайте папку проекта и инициализируйте ее:

$ mkdir youtube-text
$ cd youtube-text
$ npm init

Нажмите Enter, чтобы использовать имя по умолчанию, лицензию и т. Д., Или введите свое собственное.

Затем инициализируйте репозиторий git:

$ git init

Не забудьте создать файл .gitignore:

node_modules
secrets.js

Загрузите и установите Express, Axios и Puppeteer с помощью NPM. Puppeteer загрузит последнюю версию Chromium и потребует много места (~ 170 МБ для Mac, ~ 282 МБ для Linux, ~ 280 МБ для Win).

$ npm install --save express puppeteer axios

Если вы еще этого не сделали, зарегистрируйтесь и получите ключ Google Cloud API. На момент написания этой статьи вы можете подписаться на бесплатную пробную версию, которая предоставит кредит. Чтобы использовать Google Cloud Vision API, вам потребуется аккаунт с включенной оплатой.

В корневом каталоге нашего проекта создадим файл с именем secrets.js: он будет содержать наш ключ API, когда мы запустим наше приложение локально.

В корневом каталоге нашего проекта создадим файл с именем app.js:

Строка 1–2: Импортируйте экспресс и назначьте переменную приложения.

Строка 3: Устанавливает порт прослушивания, используя либо переменную окружения, либо 8080.

Строка 5: Если переменная NODE_ENV не является "производственной", мы импортируем файл секретов, который назначает ключевую переменную Google API. Необходимо для использования Google Cloud Vision API.

Строка 7–9: Наш маршрут / api GET. Просто отправляет пока статус 200.

Строки 11–13: обратный вызов прослушивателя приложений.

Проверка статуса №1

Запуск нашего приложения с node app и переход к http: // localhost: 8080 / api должен вернуть статус OK.

Использование Puppeteer для создания скриншотов

Теперь напишем функцию скриншота. А пока мы просто сделаем снимок экрана веб-страницы и вернем его клиенту.

Строка 1: Импортируйте модуль.

Строки 3: мы объявляем функцию, которая будет принимать строку URL и возвращать изображение в кодировке base-64. Мы сделаем это async, чтобы запускать каждую строку последовательно.

Строка 5: запускает новый экземпляр браузера. Мы могли бы передать необязательный объект параметров (см. Документацию), но сейчас в этом нет необходимости.

Строка 6: открывает новую вкладку.

Строка 7: переход к входному URL-адресу.

Строка 8: Измените размер области просмотра нашего браузера.

Строка 9: Создайте снимок экрана с объектом параметров. Мы собираемся сгенерировать строку в кодировке base-64, поэтому будем использовать

{encoding: 'base64'}

Строка 10–11: закрывает браузер и возвращает изображение. Нам не нужно await browser.close(), так как мы уже получили image.

(В документации API Puppeteer описаны все используемые здесь методы и функции; это очень полезно!)

После того, как вы добавите приведенный выше код в app.js, мы изменим наш маршрут GET.

Строка 2: Создает скриншот строки в кодировке base-64 переданного URL (на данный момент мы жестко запрограммировали его как http://youtube.com/).

Строка 3: Поворачивает изображение в кодировке base-64 и превращает его в двоичный буфер. (Если вам кажется, что нет необходимости генерировать изображение в виде строки base64, только чтобы превратить его в двоичный буфер, не волнуйтесь - мы вернемся к этому позже).

Строка 4–8: Записывает заголовки и отправляет файл изображения клиенту.

Проверка статуса # 2

На этом этапе, когда мы перейдем к http: // localhost: 8080 / api, наше приложение Express сгенерирует снимок экрана с главной страницы YouTube, а затем отправит его в браузер в виде изображения.

Создание снимка экрана видео в определенное время

Давайте сейчас сделаем скриншот видео с YouTube. Как мы передадим в приложение видео и время? Будем использовать параметры запроса!

Например, если мы хотим сделать снимок экрана этого видео в указанное время:
https://www.youtube.com/watch?v=o3ka5fYysBM&t=1740

Если мы хотим быть в состоянии RESTful, мы можем перейти к /api?videoId=o3ka5fYysBM&t=1740.

Давайте изменим нашу generateScreenshot функцию:

Пройдемся по изменениям:

Строка 9: Мы выбираем DOM-элемент видеоплеера на веб-странице YouTube.

Строка 10–13: мы скрываем элементы управления YouTube от элемента проигрывателя. Если вы хотите увидеть элементы управления / время, прошедшее на скриншоте, вы можете закомментировать этот раздел.

Строка 14: мы имитируем нажатие пользователем клавиши пробела, чтобы Кукловод воспроизвел видео.

Строка 15: Мы делаем снимок экрана, но не всей страницы. Вместо этого мы делаем снимок экрана только элемента video, который мы выбрали в строке 9.

Итак, теперь наша функция generateScreenshot делает снимок экрана видео YouTube, но как нам передать правильные параметры? Мы отредактируем маршрут GET.

Наш маршрут GET теперь будет смотреть на параметры с именем videoId и t, создавать URL-адрес YouTube на основе параметров, а затем передавать этот новый URL-адрес в нашу generateScreenshot функцию.

Строки 2–5: Проверяет, заданы ли параметры videoId и t. В противном случае он возвращает полезное сообщение об ошибке и завершает обратный вызов.

Строка 6: Использует деструктуризацию для присвоения значений videoId и t из req.query.

Строка 7. Создайте URL-адрес YouTube. (Примечание: это работает, только если параметр t представляет собой одно число в секундах).

Проверка статуса # 3

Перейдите по адресу http: // localhost: 8080 / api? VideoId = o3ka5fYysBM & t = 1740. Мы должны получить скриншот видео YouTube в нужное время.

Получение текста с помощью Google Cloud Vision API

Теперь нам нужно отправить изображение в Vision API.

Сначала мы определим функцию, которая сделает снимок экрана, который мы создали ранее, сгенерирует объект запроса JSON, а затем отправит его в API с помощью axios.

(Документация: https://cloud.google.com/vision/docs/detecting-text)

Строка 1: мы определяем переменную GOOGLE_API_KEY из переменной окружения, которая должна быть установлена ​​при импорте secrets.js.

Строка 3: мы определим нашу функцию getText как async из-за запроса POST, и в качестве входных данных она будет использовать скриншот в кодировке base64.

Строка 4–12: ​​мы определяем тело запроса в формате JSON. Мы передаем наш снимок экрана в строке 6. Поскольку это строка в кодировке base-64, мы можем передать ее туда content. Если бы у вас был URL-адрес изображения, вы могли бы вместо этого назначить URL-адрес content. Я определил тип запроса как ‘DOCUMENT_TEXT_DETECTION’ в строке 8 на случай, если изображение было насыщенным текстом.

Строка 13–16: наш axios запрос к API.

Строка 17: Мы возвращаем результаты запроса API.

Давайте отредактируем наш маршрут GET, чтобы вернуть клиенту только очищенный текст.

Строка 10: Мы вызываем getText с screenshot, который мы создали ранее, и присваиваем полученный JSON text.

Строка 11: она достигает нескольких уровней в возвращенном результате Google Vision JSON и присваивает текст нашей переменной response.

Строка 12: отправьте строку обратно.

(В качестве альтернативы, если вы хотите увидеть весь полученный JSON из Google Vision / getText, измените строки 11 и 12 на res.json(text), который будет отправлять текст вместе с данными о местоположении.)

Проверка статуса # 4

Переход к http: // localhost: 8080 / api? VideoId = o3ka5fYysBM & t = 1740 вернет строку вместо изображения.

Развертывание на Heroku

Если вы хотите развернуть это в Heroku, вам нужно сделать несколько дополнений:

В функции generateScreenshot:

Передайте объект с указанным выше аргументом args в launch().

В package.json обязательно укажите node версию и start скрипт:

// ...
"engines": {
  "node": "9.8.0"
},
"scripts": {
  "start": "node app"
},
// ...

Вам также необходимо включить buildpack для кукловода в дополнение к buildpack узла. Один из способов добавить это может быть через Heroku CLI:

$ heroku buildpacks:add https://github.com/jontewks/puppeteer-heroku-buildpack
$ heroku buildpacks:add heroku/nodejs

Вы должны иметь возможность развернуть приложение на Heroku. Однако вы можете получить ошибки H12, потому что Heroku имеет 30-секундный лимит тайм-аута для запросов. Я оставлю эту часть на ваше усмотрение.

Последние мысли

Кукольник - довольно интересный инструмент. Немного изменив код, который я описал выше, вы можете использовать его для создания таких файлов, как GIF. Я хотел бы глубже погрузиться в это и посмотреть, что еще возможно. Если у вас есть какие-либо комментарии, вопросы или исправления, я буду рад их услышать!

Если вы хотите клонировать приведенный выше код, вот URL-адрес GitHub:
https://github.com/djung31/youtube-text