JavaScript | Как получить текст из субтитров YouTube?

JavaScript | Как получить текст из субтитров YouTube?

YouTube умеет показывать субтитры, а ещё он умеет переводить субтитры на любой язык. Меня интересовало получение полноценного связного текста перевода для видеоролика.

Задача

Нужно получить полноценный «очищенный» текст силами JavaScript и инструментами разработчика в браузере. Никаких редакторов кода.

 

1. Получение файла субтитров

Для начала откроем нужный нам видеоролик и включим у него субтитры. Пусть это будет ролик с YouTube-канала «Google Chrome Developers» — https://youtu.be/9Qtvjd0UbAs

Кнопка включения субтитров на YouTube
Кнопка включения субтитров на YouTube

После включения субтитров под белой иконкой появится красная полоса, которая информирует о «включенном» состоянии субтитров. В верхнем левом углу указывается язык воспроизведения субтитров.

Субтитры включены
Субтитры включены

Включаем инструменты разработчика в браузере. Переключаем язык с английского на русский.

Инструменты разработчика. Смена языка субтитров.
Инструменты разработчика. Смена языка субтитров.

 

Выбираем «Перевести». Находим русский язык.

Выбрали перевод субтитров на русский язык
Выбрали перевод субтитров на русский язык

В момент клика по нужному нам языку на сервер отправляется запрос.

Запрос на перевод субтитров на русский язык
Запрос на перевод субтитров на русский язык

Запрос был отправлен при помощи XMLHttpRequest. В ответе пришёл объект JSON.

JSON объект в ответе сервера
JSON объект в ответе сервера
Заголовки ответа. Нам интересен "content-type: application/json; charset=UTF-8"
Заголовки ответа. Нам интересен «content-type: application/json; charset=UTF-8»

В ответе сервера мы уже видим русские буквы, слова и предложения. Но в таком виде нам не удобно работать с текстом т. к. он разделён временными метками.

 

2. Работа с объектом JSON в браузере

Нажимаем правую кнопку мыши над содержимым поля «Response» в инструментах разработчика.

Открыть JSON в новой вкладке
Открыть JSON в новой вкладке

Документ открывается в новой вкладке. Документу присваивается базовая HTML-разметка.

Наш JSON оборачивается элементом pre
Наш JSON оборачивается элементом pre

С этого момента мы можем начать писать сценарий, при котором будет получен «чистый» текст из русских букв.

 

3. Программирование на JavaScript

Для начала поместим содержимое объекта JSON в переменную и будем с ним работать.

В переменную «a» заносим коллекцию HTML-элементов pre. В нашем случае всё просто т. к. на странице всего один элемент pre.

var a = document.getElementsByTagName("pre")
Получаем HTML-коллекцию элементов pre со страницы
Получаем HTML-коллекцию элементов pre со страницы

Преобразовываем HTML-коллекцию в массив и заносим в переменную «b«.

var b = Array.from(a)
Преобразование коллекции а массив
Преобразование коллекции а массив

Теперь мы можем получить внутреннее содержимое между закрывающим и отрывающим тегом pre. Получаем первый элемент массива «b» и сразу выводим его innerHTML.

var c = b[0].innerHTML
Внутреннее содержимое элемента pre
Внутреннее содержимое элемента pre

 

Сейчас в переменной «c» лежит строковый тип данных. А нам нужно получить объект. Мы хорошо видим что строка легко преобразуется в объект. Преобразуем.

var obj = JSON.parse(c)
JSON.parse
JSON.parse

По структуре объекта нам нужно дотянуться до ключа «events«, значением которого является нужный нам массив с текстовыми кусками. Вытягиваем массив.

var arr1 = obj.events
Массив из объектов
Массив из объектов

В переменную «arr1» попал массив из объектов. Нам это тоже не подходит и мы будем понемногу извлекать содержимое из объектов и генерировать «облегчённые» массивы.

Первым нас будет встречать индекс массива.

Вторым — ключ «segs«

Третьим — снова индекс массива

Четвёртым — ключ «utf8«

Логика вложенности массивов/объектов
Логика вложенности массивов/объектов

 

Структура повторяется из по каждому индексу массива, поэтому сразу применим преобразования по полным (глубинным) путям. Воспользуемся методом map(), который работает с прототипами объектов Array.

var arr2 = arr1.map(t => {return t.segs[0].utf8})
Массив из куском текста
Массив из куском текста

Мы уже очень близко к итоговому результату. Нас разделяет только этап «склейки» элементов массива. Удобство YouTube заключается в том, что нам не нужно будет использовать разделители между текстовыми кусками. Используем метод join(separator)

var str = arr2.join("")
Нужный нам текст без лишних обвязок
Нужный нам текст без лишних обвязок

Мы получили «чистый» текст, который можем использовать для последующего прочтения или написания публикации в сети интернет.