Открытие и воспроизведение видеофайлов python
Решил написать свой проводник. Уже реализованы открытие изображений и текстовых файлов. Решил сделать открытие видео, но всё пошло не так. Из рабочих способов, которые у меня были, это запуск помощью OpenCV, но звука не было, и с помощью python-vlc, но проигрыватель не закрывается. В интернете нужного решения не нашёл. Подскажите либо решение одной из двух вышепредставленных, либо новый вариант воспроизведения видео. Заранее спасибо!
import time, vlc def video(source): vlc_instance = vlc.Instance() player = vlc_instance.media_player_new() media = vlc_instance.media_new(source) player.set_media(media) player.play() time.sleep(0.5) duration = player.get_length() print("Duration : " + str(duration)) video("videos/example.mkv")
Отслеживать
задан 19 дек 2021 в 15:40
1 3 3 бронзовых знака
Оригинальный «Проводник» не занимается воспроизведением видео
19 дек 2021 в 15:44
Ник Лог вы забыли опубликовать свой пример, который демонстрирует проблему.
19 дек 2021 в 15:57
andreymal, я хочу сделать запуск видео из проводника, открывая видеофайл в vlc, или другой программе воспроизведения видео. Эту программу можно написать самому, но как?
19 дек 2021 в 16:22
Хороший проводник будет не пытаться использовать какой-то конкретный плеер, он прочитает выбранное пользователем приложение по умолчанию из системных настроек и будет использовать его. В питоне для Windows есть специальная функция для этой цели: os.startfile(source) stackoverflow.com/questions/434597
Мой pet-проект: видеоплеер с переводимыми субтитрами LinguaPlayer
У меня было достаточно много 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 реплик, то цикл завершается быстро. Возможно, многим будет проще воспринять описанный алгоритм в виде кода:
// Объект реплики: порядковый номер, время начала отображения (в миллисекундах), время конца отображения, текст class Cue < public readonly index: number; public readonly startTime: number; public readonly endTime: number; public readonly text: string; constructor(index: number, startTime: number, endTime: number, text: string) < this.index = index; this.startTime = startTime; this.endTime = endTime; this.text = text; >> interface CueIndex < // Ключ индекса это целая секунда (без миллисекунд) и массив порядковых номеров реплик, // которые начинают или заканчиваются в течение этой секунды [key: number]: number[]; >class SubtitlesTrack < private readonly cues: Cue[]; private index: CueIndex = <>; constructor(cues: Cue[]) < this.cues = cues; // На входе у нас просто массив реплик, нужно проиндексировать this.indexCues(); >private indexCues() < this.cues.forEach((cue: Cue) => < // Переводим время начала и конца реплики из миллисекунд в секунды и берём только целую часть const startSecond = Math.floor(cue.startTime / 1000); const endSecond = Math.floor(cue.endTime / 1000); // Добавляем реплику (её порядковый номер) в индекс this.addToIndex(startSecond, cue); // Бывает, что реплика началась в одной секунде, и отображается до следующей или даже держится несколько секунд // Такую реплику следуют добавить также в индекс секунды окончания if (endSecond !== startSecond) < this.addToIndex(endSecond, cue); >>); > private addToIndex(secondNumber: number, cue: Cue): void < // Если это первая реплика в данной секунде, инициализируем ключ индекса пустым массивом if (!this.index[secondNumber]) < this.index[secondNumber] = []; >// Затем в массив реплик добавим порядковый номер новой реплики this.index[secondNumber].push(cue.index); > // Метод поиска реплики public findCueForTime(timeInSeconds: number): Cue|null < // Событие плеера timeupdate присылает время сразу в секундах // Поэтому сразу берём целую часть const flooredTime = Math.floor(timeInSeconds); // Выбираем проиндексированные реплики для этой секунды const cues = this.index[flooredTime]; let currentCue = null; // Если на данной секунде есть реплики if (cues) < // Проходимся по каждой for (let index of cues) < const cue = this.cues[index]; // И смотрим, совпадает ли интервал времени начала и конца реплики с текущем временем в плеере if (this.isCueInTime(timeInSeconds, cue)) < // Если да, то устанавливаем значение текущей реплики и останавливаем цикл currentCue = cue; break; >> > // Вернём текущую реплику или null, если для данного времени реплики нет return currentCue; > public isCueInTime(timeInSeconds: number, cue: Cue): boolean < const timeInMilliseconds: number = timeInSeconds * 1000; return timeInMilliseconds >= cue.startTime && timeInMilliseconds >
Таким образом, вместо того, чтобы 4 раза в секунду обходить массив из тысяч элементов, необходимо лишь сделать одно обращение по индексу, и пройтись по массиву длинной от 1 до 4.
Перед тем как выводить получаемые реплики я разбивал их на предложения и на слова с помощью библиотеки node-sentence-tokenizer. Всё это дело я оборачивал в элементы div с классами sentence и word соответственно, чтобы иметь возможность вешать на них события в дальнейшем и выполнять перевод. Вот так выглядит код:
import Tokenizer from 'sentence-tokenizer'; function formatCue(text: string): string < const brMark: string = '[br]'; const tokenizer = new Tokenizer(); // Заменяем переносы строк на псевдотэг для удобной работы с переносами в дальнейшем text = text .replace(/\r\n/g, ` $`) .replace(/\r/g, ` $`) .replace(/\n/g, ` $`); // Устанавливаем text как сущность для обработки tokenizer.setEntry(text); // Разбиваем текст на предложения const sentenceTokens: string[] = tokenizer.getSentences(); // Проходимся по предложениям const sentencesHtml: string[] = sentenceTokens.map((sentenceToken: string, index: number) => < // Разбиваем предложение по словам const wordTokens: string[] = tokenizer.getTokens(index); // Идём по каждому слову const wordsHtml: string[] = wordTokens.map((wordToken: string) =>< let brTag: string = ''; // Если после слова есть псевдотэг переноса, удаляем его и устанавливаем html тэг переноса строки if (wordToken.includes(brMark)) < wordToken = wordToken.replace(brMark, ''); brTag = '
'; > // Оборачиваем слово в span с классом word и добавляем тэг br, если надо return `$$ `; >); // Склеиваем слова обратно, в строку, оборачиваем предложение в в span с классом sentence return `$ `; >); // Склеиваем предложение обратно в строку const html: string = sentencesHtml.join(' '); return html; >
Далее я прикрутил Microsoft Translator для осуществления перевода, и плеер для изучения английского был готов.
Чего не хватает проекту, чтобы развиваться
Конечно, на данный момент плеер даже не является MVP, это скорее proof of concept. И у меня есть множество идей по развитию данного проекта. В первую очередь хочется добавить поддержку словарей, например английского и англо-русского, а также интегрировать Urban Dictionary для распознавания сленга, а также различных современных слов и фраз. Во вторую очередь есть мысль реализовать интеграции с сервисами по изучению иностранных языков, такими как LinguaLeo или Skyeng. Это позволило бы добавлять незнакомые слова в персональный словарь на сервисе и учить их позже. Или же импортировать свой словарь в Anki. Также можно было бы добавить поддержку изучения других языков.
Но, прежде чем приступить к реализации задуманных функций, необходимо решить ряд технических и концептуальных проблем. Моя изначальная идея заключалась в том, чтобы можно было смотреть свои старые и излюбленные фильмы, пылящиеся на жёстком диске. И здесь возникает серьёзная техническая проблема, а именно – слабая поддержка кодеков в браузере Chromium. Глядя на список поддерживаемых форматов, можно заметить, что по факту в приложении можно проиграть лишь файлы с видеокодеком H.264 и аудиокодеком FLAC либо MP3. Нужно очень постараться чтобы найти именно такой файл. Да никто и не будет заниматься подобным – сейчас все избалованы стриминговыми
сервисами. Не говоря уже о вопросах лицензирования, что является большой, концептуальной проблемой.
Таким образом, главный блокирующий фактор сейчас – это контент. Он должен без проблем играть в приложении, должна быть возможность легко и быстро его получать, а также, он не должен нарушать лицензии и авторские права. Как только удастся решить вопрос с контентом, я с радостью продолжу работу над проектом. А пока предлагаю всем энтузиастам скачать и попробовать концепт-версию приложения.
Создание видеоплеера?
Есть конструктор PlayerJS. Можно собрать такой же плеер и не прогать свой велосипед.
Ответ написан более двух лет назад
Комментировать
Нравится Комментировать
Ваш ответ на вопрос
Войдите, чтобы написать ответ

- Веб-разработка
- +2 ещё
Будет ли аналитика сайта учитывать источник трафика, если в поле referer — strict-origin-when-cross-origin?
- 1 подписчик
- вчера
- 31 просмотр

- Веб-разработка
Как сделать вызов событий из php в python, как передать данные из php в python?
- 1 подписчик
- 17 нояб.
- 77 просмотров

- Веб-разработка
Существует ли что-то, позволяющее сразу перейти к разрабатываемому элементу страницы?
- 2 подписчика
- 17 нояб.
- 170 просмотров

- Веб-разработка
- +1 ещё
Как правильно реализовать ЭЦП JaCartа?
- 1 подписчик
- 17 нояб.
- 29 просмотров

- Веб-разработка
Как обновить страницу напрямую через сервер?
- 3 подписчика
- 17 нояб.
- 433 просмотра

- Веб-разработка
Веб-сервер дома на виндовс для работы с python?
- 2 подписчика
- 16 нояб.
- 442 просмотра

- Веб-разработка
Svelte минимальный размер сайта?
- 2 подписчика
- 15 нояб.
- 233 просмотра

- Веб-разработка
- +1 ещё
Как можно открыть программу (exe) находясь на своем веб-сайте?
- 1 подписчик
- 15 нояб.
- 207 просмотров

- Веб-разработка
Как сайт понимает, что я был на нём, если я запретил сохранять cookie, а также удалил все данные с него?
- 3 подписчика
- 14 нояб.
- 543 просмотра

- HTML
- +2 ещё
Как убрать элемент со странице, которого нет в разметке html?
- 1 подписчик
- 14 нояб.
- 122 просмотра
от 40 000 до 180 000 ₽
от 50 000 до 150 000 ₽
Dомиан • Ростов-на-Дону
19 нояб. 2023, в 18:58
5000 руб./за проект
19 нояб. 2023, в 18:12
25000 руб./за проект
19 нояб. 2023, в 16:22
10000 руб./за проект
Минуточку внимания
Присоединяйтесь к сообществу, чтобы узнавать новое и делиться знаниями
- Как отследить запросы?
- 2 подписчика
- 1 ответ
- 2 подписчика
- 1 ответ
- 2 подписчика
- 1 ответ
- 2 подписчика
- 2 ответа
- 3 подписчика
- 2 ответа
- 2 подписчика
- 1 ответ
- 2 подписчика
- 3 ответа
- 2 подписчика
- 1 ответ
- 2 подписчика
- 1 ответ
- 2 подписчика
- 1 ответ
Какие есть готовые видеоплееры (скрипты) для Python 3.x?
Нужен видеоплеер выполняющие примитивные функции: воспроизведение, пауза, стоп, перемотка.
+Возможность воспроизведения субтитров.
Не хочу изобретать велосипед, все что находил до этого момента было для python 2.
Или хотя бы подскажите какую библиотеку лучше использовать для этих целей.- Вопрос задан более трёх лет назад
- 1058 просмотров
2 комментария
Оценить 2 комментария

Задача не понятна
Решения вопроса 0
Ответы на вопрос 1
Пишу на Python за карму и за деньги
Солидарен с комментариями к вопросу — 1. задача не ясна. 2. погуглить можете и сами.
Но все же попробую угадать — вам нужно в некоем приложении воспроизвести видео с субтитрами? Вы можете попробовать использовать стороннее приложение для этого, которое через командную строку будет принимать команды для отображения видео (для Windows можно использовать Media Player Classic — https://mpc-hc.org/).Ответ написан более трёх лет назад
Evgenzsin @Evgenzsin Автор вопросаНужен код (+скорее всего, библиотеки к нему), который воспроизведет видео+субтитры.
Далее этот код (видеоплеер) будет добавлен в мой самописный код, предназначенный для работы с субтитрами.
Второй день гугления оказался удачней: нашел минимум два плеера для python3 (Вчера натыкался на вторые) 1)Kivy Video player 2) mplayer.py. Есть ли книга/описание (ру/ингл) как работает такой код?
Evgenzsin: По этим вопросам опыта нет, к сожалению. Помочь тут не смогу.
Ваш ответ на вопросВойдите, чтобы написать ответ

- Python
- +1 ещё
Как сделать форму с добавлением нескольких элементов на django?
- 1 подписчик
- 3 часа назад
- 22 просмотра
