Мой pet-проект: видеоплеер с переводимыми субтитрами LinguaPlayer
Рассказ о возникновении идеи и создании приложения, которое позволяет переводить слова и целые фразы прямо во время просмотра кино
2К открытий2К показов
У меня было достаточно много pet-проектов разной степени готовности. Среди них: социальная сеть для писателей, генератор CSS-спрайтов, Телеграм бот для знакомств по интересам и многое другое. Сегодня речь пойдёт о моей последней разработке.
Как многие в наши дни, я учу английский. Думаю, так же многие знают, что эффективным подходом в этом деле является максимальное погружение в среду. Интерфейс телефона на английском, записи в блокноте на английском, смотреть кино на английском с английскими субтитрами. Смотря кино в оригинале, рано или поздно возникает потребность перевести то или иное слово или фразу, которые мелькают на экране каждые несколько минут. Без них вообще ничего не понятно.
Идея проекта
Так у меня и родилась идея видеоплеера с переводимыми субтитрами. Приложение позволяет переводить слова и целые фразы прямо во время просмотра кино. С ним отпадает необходимость переключаться между приложениями или брать в руки смартфон. Знакомьтесь – LinguaPlayer.
Схема работы простая. Пользователь открывает файл с фильмом и файл субтитров. Смотрит фильм как обычно. Однако теперь в его распоряжении помимо стандартных горячих клавиш есть клавиши для перевода каждого слова по отдельности, перевода целых предложений, перемотки от реплики к реплике. Также присутствует перевод посредством наведения курсора мыши на слова или выделения нужного куска текста. Приложение доступно для Windows и MacOS. Все подробности можно почитать на страничке приложения.
Технологический стек
Плеер реализован на платформе Electron, т. е. по сути это браузер Chromium внутри которого бежит обычное веб-приложение. На этой технологии построено большое количество различных приложений – удачных и не очень. Наиболее известные примеры это Visual Studio Code, Skype, Slack. Electron предоставляет некоторые системные API, которые недоступны JavaScript, запущенному в обычном браузере. Это позволяет делать приложения более функциональными и близкими по возможностям и пользовательскому опыту к нативным. Что касается всего остального – разработчику доступен абсолютно любой стек, применимый в вебе. Будь то чистый JavaScript, Angular, jQuery, Vue – что угодно.
Для LinguaPlayer я выбрал привычный стек, с которым работаю каждый день: TypeScript, React, MobX, Webpack. Я планировал сделать прототип за вечер, так как задача выглядела легко: дал приложению файл с видео и файл с субтитрами, прикрутил переводчик и готово. С этой частью проблем не возникло. Однако, как оказалось, встроенный в браузеры движок отображения субтитров не имеет никаких средств взаимодействия с текстом реплик. Что я имею в виду. Реплики титров хоть и появляются поверх видео, но в DOM никаких упоминаний о них нет. Другими словами, нет возможности распарсить текст, разбить его по словам и предложениям, повесить обработчики нажатий клавиш или зарегистрировать события мыши.
Решение интересных задач
Таким образом, мне пришлось решить две задачи. Первая — это парсинг srt-файлов с титрами с последующей синхронизацией реплик с видеопотоком. Вторая – разбивка реплик на токены, чтобы была возможность взаимодействовать с каждым словом и предложением по отдельности.
Для парсинга титров я взял библиотеку node-webvtt. Для синхронизации титров изначально я написал логику «в лоб». Подписавшись на событие video-элемента «timeupdate», я просто ходил по массиву реплик и сравнивал текущее время видео с временем реплик. Однако, событие «timeupdate» срабатывает четыре раза за секунду, а реплик в среднем фильме несколько тысяч. Всё это дело жутко тормозило.
Для оптимизации данного процесса я сделал простой hash map. Его ключом является секунда (целая, без миллисекунд), а значением – массив номеров реплик, которые должны быть показаны в эту секунду. Выглядело это примерно так:
В каждой секунде может быть от 0 до примерно 4 реплик — человек имеет ограничения и вряд ли сможет прочитать большее количество текста за секунду. Таки образом, при обновлении времени воспроизведения, всё что необходимо сделать, это выделить из него целую часть и обратиться с этим значением к hash map. Если на этой секунде реплик нет, значит ничего больше не делаем. Если на этой секунде есть реплики, то итерируемся по вернувшемуся массиву и ищем, какая именно реплика должна быть показана сейчас. Так как на секунду может быть до 4 реплик, то цикл завершается быстро. Возможно, многим будет проще воспринять описанный алгоритм в виде кода:
Таким образом, вместо того, чтобы 4 раза в секунду обходить массив из тысяч элементов, необходимо лишь сделать одно обращение по индексу, и пройтись по массиву длинной от 1 до 4.
Перед тем как выводить получаемые реплики я разбивал их на предложения и на слова с помощью библиотеки node-sentence-tokenizer. Всё это дело я оборачивал в элементы div с классами sentence и word соответственно, чтобы иметь возможность вешать на них события в дальнейшем и выполнять перевод. Вот так выглядит код:
Далее я прикрутил Microsoft Translator для осуществления перевода, и плеер для изучения английского был готов.
Чего не хватает проекту, чтобы развиваться
Конечно, на данный момент плеер даже не является MVP, это скорее proof of concept. И у меня есть множество идей по развитию данного проекта. В первую очередь хочется добавить поддержку словарей, например английского и англо-русского, а также интегрировать Urban Dictionary для распознавания сленга, а также различных современных слов и фраз. Во вторую очередь есть мысль реализовать интеграции с сервисами по изучению иностранных языков, такими как LinguaLeo или Skyeng. Это позволило бы добавлять незнакомые слова в персональный словарь на сервисе и учить их позже. Или же импортировать свой словарь в Anki. Также можно было бы добавить поддержку изучения других языков.
Но, прежде чем приступить к реализации задуманных функций, необходимо решить ряд технических и концептуальных проблем. Моя изначальная идея заключалась в том, чтобы можно было смотреть свои старые и излюбленные фильмы, пылящиеся на жёстком диске. И здесь возникает серьёзная техническая проблема, а именно – слабая поддержка кодеков в браузере Chromium. Глядя на список поддерживаемых форматов, можно заметить, что по факту в приложении можно проиграть лишь файлы с видеокодеком H.264 и аудиокодеком FLAC либо MP3. Нужно очень постараться чтобы найти именно такой файл. Да никто и не будет заниматься подобным – сейчас все избалованы стриминговыми
сервисами. Не говоря уже о вопросах лицензирования, что является большой, концептуальной проблемой.
Таким образом, главный блокирующий фактор сейчас – это контент. Он должен без проблем играть в приложении, должна быть возможность легко и быстро его получать, а также, он не должен нарушать лицензии и авторские права. Как только удастся решить вопрос с контентом, я с радостью продолжу работу над проектом. А пока предлагаю всем энтузиастам скачать и попробовать концепт-версию приложения.
2К открытий2К показов