Скрипт сборщика цитат и распознания текста из видео на Python +12


Пост о скрипте, который скачивает видео с youtube и распознает в нем текст. Начать решил сразу с практической реализации. «Vdudictionary» — Скрипт сборщика сборника цитат героев «Вдудь» на Python. Юрий Дудь и его проект «Вдудь» не нуждается в представлении. Самые горячие интервью, которые интересно смотреть. Юрий Александрович умеет сделать интересное шоу, независимо от того, знаете ли Вы героя конкретного выпуска, являетесь его фанатом или впервые слышите это имя.

Сколько у Вас см? Что Вы скажете Путину? Слушаете ли Вы OXY?


Эти и многие другие вопросы теперь ассоциируются с Дудем. Когда интервьюируемый произносит фразу преисполненную мудростью, заботливые монтажеры аккуратно выводят ее на экран наших с Вами мониторов, чтобы донести до нас всю суть. Моей целью было закристаллизовать эту мудрость поколений и создать словарь «Вдудексикон» или «Vdudictionary».

Естественно человеку, пусть и не обремененного специфическим IT бэкграудом, не надлежит руками собирать эти изречения. Для этого я набросал скрипт на python.



Первым делом нам нужен файл, который будем обрабатывать. Для скачивания видео с Youtube я использовал модуль pytube.

pip install pytube

Пример скачивания файла с youtube

from pytube import YouTube
a=YouTube('https://www.youtube.com/watch?v=RNbXm8WKmow')
a.streams.first().download()

Файл скачали. Теперь начнем методично определять кадры с концентрированным смыслом, с мудростью современников, с изречениями героев нашего времени.



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

a,contours,h = cv2.findContours(gray3, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for i in contours:
    cv2.drawContours(gray3,[i],0,(0,0,255),1)

Для установки cv2 для python3 на raspberry3 пришлось установить много пакетов из-за зависимостей. Возможно, некоторые пакеты избыточны, это из-за моей неопытности, именно так все завелось.


sudo apt-get install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get -y install libopencv-dev
sudo apt-get -y install build-essential checkinstall cmake pkg-config yasm
sudo apt-get -y install libtiff4-dev libjpeg-dev libjasper-dev
sudo apt-get -y install libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev libxine-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev
sudo apt-get -y install python-dev python-numpy
sudo apt-get -y install libtbb-dev
sudo apt-get -y install libqt4-dev libgtk2.0-dev
sudo apt-get -y install libfaac-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev
pip install opencv-python

Ставим tesseract — это OCR движок, необходимый для оптического распознавания текста.


sudo apt-get install tesseract-ocr
sudo pip3 install pytesseract
sudo pip3 install tesseract

В выпусках используется весьма специфическая гарнитура, это затрудняет распознание. Вообще же для кириллицы устанавливаем словарь. Скачиваем и переносим в /usr/share/tesseract-ocr/tessdata.



Скрипт на входе получает адрес ролика на youtube. Скачивает файл, начинает обрабатывать по одному кадру в 5 секунд. Если в кадре есть квадрат, вырезаем его, обесцвечивает, повышаем контрастность и распознаем. Если строка меньше 15 символов, не учитываем ее. Можете, конечно, использовать и строку меньше 15 символов, но как сказала одна из героинь передачи:
-Я не знаю, пацаны, как Вы живете с маленькими строками.

Заносим в лог файл текст, время и ссылку на момент на youtube. Пропускаем 5 секунд( не спрашивайте почему именно эта цифра первой пришла в голову, проверив не нашел наложения двух цитат в пределах этого времени). Можно удалить файл видео и приступить к следующему выпуску.

Полный код скрипта:

Скрипт на Python 3
import cv2
import pytesseract
import numpy as np
from pytube import YouTube
import os

nameofvideo="RNbXm8WKmow"

a=YouTube('https://www.youtube.com/watch?v='+nameofvideo)
a.streams.first().download()
title=a.title
title2=title.replace("/","").replace(",","").replace(".","")+".mp4"
os.rename(title2, "youtubefile.mp4")
print(title)
f=open('/var/www/python/'+str(nameofvideo)+'.txt','w')
f.write(title+"<br>")
f.write('<table><tr><td>Время</td><td>Цитата</td><td>Ссылка</td></tr>')

spisoksimvolovpodudalenie=["*","/","|","\\",")","(","}","{","+","`","~","№","",":","$","#","@","%","[","]","&","^","'  "]
def udaleniesimvolov(stroka):
	for element in spisoksimvolovpodudalenie:
		stroka=stroka.replace(element,"")
	return stroka

vidcap = cv2.VideoCapture('youtubefile.mp4')
vidcap.set(cv2.CAP_PROP_POS_AVI_RATIO,1)
durationsec=int(vidcap.get(cv2.CAP_PROP_POS_MSEC)/1000)
print("duration: "+str(durationsec)+" sec")

for thissec in range(0,durationsec,5):
	vidcap.set(cv2.CAP_PROP_POS_MSEC,thissec*1000)
	success,image = vidcap.read()
	gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	gray2 = cv2.addWeighted( gray, 1.5, gray, 0, 0.5)
	gray3 = gray2[450:670,0:1280]
	if success:
		print(str(thissec)+" sec.")
		text = udaleniesimvolov(pytesseract.image_to_string(gray3, lang='rus'))
		if len(text)>15:
			print (text)
			f.write('<tr><td>'+str(thissec)+'</td><td>'+text+'</td><td><a href="https://www.youtube.com/watch?v='+nameofvideo+"&t="+str(thissec)+'">Ссылка</a></td></tr>')
		print("----")
f.write('</table>')
f.close()


Пример работы скрипта
Толоконникова — бисексуальность, FACE, тюрьма / вДудь
Время, c. Цитата
95 «АКТИВИСТЫ НЕ ДОЛЖНЫ НЕНАВИДЕТЬ МЕНТОБ.
ОНИ ДОЛЖНЫ ПОПЫТДТЬСЯ ПОННТЬ,
ЧТО МЕНТА ПОБУДИЛО БЫТЬ МЕНТОМ»
>
195 ПЕТР ВЕРЗИЛОВ — УЧАСТНИК PUSSY RIOT
БЫВШИИ МУЖ НАДЕЖДЫ ТОЛОКОННИКОВОИ
>
255 Екатерина Самуцевич >
570 ОБОЖАЮ ТРИКОТАЖ! >
595 ' вляДЬМЦР сорбйПн

>
990 ПЕТР ВЕРЗИЛОВ В ЮНОСТИ ЖИЛ В ЯПОНИИ ВМЕСТЕ С РОДИТЕЛЯМИ.
ОТЕЦ ПЕТРА — ФИЗИК-ЯДЕРЩИК
>
995 ПЕТР ВЕРЗИЛОВ В ЮНОСТИ ЖИЛ В ЯПОНИИ ВМЕСТЕ С РОДИТЕЛЯМИ.
ОТЕЦ ПЕТРА — ФИЗИК-ЯДЕРЩИК
>
1270 11 СЕНТЯБРЯ 2018 ГОДА ПЕТР внрзипов БЫЛ госпитдлизировдн
в токсикоувднимдционуов ОТДЕЛЕНИЕ
городском клиническом Больницы имени вдхрушиных
>
1275 15 СЕНТЯБРЯ БЫЛ ДОСТАВЛЕН ЧАСТНЫМ САМОЛЕТОМ
В БЕРЛИНСКУЮ КЛИНИКУ СНАШТЕ
>
1280 18 СЕНТЯБРЯ 2018 ГОДА БЕРЛИНСКИЕ ВРАЧИЗАЯВИПИ
СКОРЕЕ ВСЕГО, ВЕРЗИЛОВ БЫЛ ОТРАВЛЕН СКОПОЛАМИНОМ.
26 СЕНТЯБРЯ БЫЛ ВЫПИСАН ИЗ БЕРЛИНСКОИ КЛИНИКИ
>
1285 18 СЕНТЯБРЯ 2018 ГОДА БЕРЛИНСКИЕ ВРАЧИ ЗАЯВИЛИ
СКОРЕЕ ВСЕГО, ВЕРЗИЛОВ БЫЛ ОТРАВЛЕН СКОПОЛАМИНОМ.
26 СЕНТЯБРЯ БЫЛ ВЫПИСАН ИЗ БЕРЛИНСКОИ КЛИНИКИ
>
1395 «МЕДИАЗОНА» — интврнвт-издднив про суды,
АРЕСТЫ и рорсию. основднноЁ в свнтявув 2014 годя
НАДЕЖДОИ тол_оконниковои и МАРИЕИ Алехинои
>
1590 «Если что- то СТРАШНОЕ прейсХЬдиі зі? нЁзндчит, '
что ты ДОЛЖЕН от СЕБЯ откдздтьря»
>
1760 йоко оно — ОБЩЕСТВЕННЫЙ ДЕЯТЕЛЬ, ВДОВА ДЖО " …
ПЕ
ВИЦА, ХУДОЖНИК,
>
2040 «ЕСЛИ У КОГО-ТО БЕЗУМНЫЕ РОДИТЕЛИ,
ЭТО, СКОРЕЕ, ПОВОД ДЛЯ РЕСПЕКТ!-»
>
2330 «ВНРЕННЯЯ МАМА»
>
2425 ГРАД КИТЕЖ — ЗАТОНУВШИЙ ГОРОД,_НАХ0ДИВШИЙСЯ‚ ПО ПРЕДАНИЮ,
В ОЕВЕРНОИ ЧАСТИ НИЖЕГОРОДСКОИ ОБЛАСТИ,
НА БЕРЕГАХ ОЗЕРА СВЕТЛОЯР
>
2515 «мы ЖЕМ ЛОБСЕРА и пОмогд
здключиным и ПИСАТЕЛЯМ»
>
2550 СЕЙЧАС- В ЖЕСТКОЙ ОППОЗИЦИИ РООСИЙ ›. '
ЖИВЕТ И РАБОТАЕТ В США
>
2745 ТОЛОКОННИКОВА ПРОБЫЛА В ТЮРЬМЕ 661 ДЕНЬ.
. С 3 МАРТА 2012 ГОДА ПО 23 ДЕКАБРЯ 2013 ГОДА
У мд.
>
2985 ВПТСН — ТЕРМИН, ОБОЗНАЧАЮЩИЙ НА СЛЕНГЕ
ЛГБТ-СООБЩЕСТВА МУЖЕПОДОБНУЮ ДЕВУШКУ ‘ ‚
00 СТРИЖКОИ «ПОД МАЛЬЁИ_К_А»
>
2990 ВЦТСН — ТЕРМИН, ОБОЗНАЧАЮЩИЙ НА СЛЕНГЕ _
ЛГБТ-СООБЩЕСТВА МУЖЕПОДОБНУЮ ДЕВУШКУ
СО СТРИЖКОИ «ПОД МАЛЬЧИКА»
>
3280 «ТАКАЯ РУССКАЯ РАЗА «НУ ТЫ
;„б?
>
3290 ШИЗО — ШТРАФНОЙ ИЗОЛЯТОР. ОТДЕЛЕНИЕ ИСПРАВИТЕЛЬНОГО УЧРЕЖДЕНИЯ,
ГДЕ РАОПОЛОЖЕНЫ КАМЕРЫ ДЛЯ НАРХШИТЕЛЕИ РЕЖИМА СОДЕРЖАНИЯ.
ЧЕЛОВЕК, ПОМЕЩЕННЫИ В ШТРАФНОИ ИЗОЛЯТОР,
СУЩЕСТВЕННО ОГРАНИЧЕН В ПРАВАХ
‚ь ›, — "
>
3315 «ЧЕЛОВЕК, котбрый долго сидит, «Е;
ПЕРЕПРИДУМЬЩАЕТ свою жизнь здново»; 3
>
3510 ПОСЛЕ АКЦИИ В ХРАМЕ ХРИСТА --'‚ПАСИТЕЛЯ БЫЛИ ЗАДЕРЖАНЫ И
ОСУЖДЕНЫ ТРИ УЧАСТНИЦЫ РПЗЗУ КЮТ
НАДЕЖДА ТОЛОКОННИКОВА, МАРИЯ АЛЕХИНА И ЕКАТЕРИНА САМУЦЕВИЧ
>
3540 ЕКАТЕРИНА САМУЦ
ПОЛУЧИЛА ДВА ГОДА УСЛОВНО
>
3660 «МОЛОДЕЖЬ дико тРАвмируЁ. __
что у ндс НЕТ сЕксудльного оврдзовдния»; ‘
>
3740 НАДЕЖДА ТОЛОКОННИКОВА ДВАЖДЫ ОБЪЯВЛЯЛА ГОЛОДОВКУ
В МОРДОВОКОЙ КОЛОНИИ Н° 14 О ТРЕБОВАНИЕМ ПЕРЕВОДА
В ДРУГОЕ МЕСТО ОТБЫТИЯ НАКАЗАНИЯ
>
4275 РЕЧЬ ПРО АКЦИЙ РПЗЗУ РЮТ СМИЛИЦИОНЕР ВСТУПАЕТ В ИГРУ» _
В ФИНАЛЕ ЧМ-2018 В МОСКВЕ
>
4495
'
«СОЧЕТАНИЕ ДИЧИ И ПОЗИЦИИ»
>
4735 «ЕСЛИ У МЕНЯ БУДЕТ ПЛОХАЯ РИФМА И ХОРОШАЯ,
Я ВЫБЕРУ ПЛОХУЮ»
>
4755 «ЗООПАРКОВАЯ ИСТОРИЯ»
>
4800 БЕРНИ САНДЕРС — КАНДИДАТ В ПРЕЗИДЕ_НТЫ США
НА ВЫБОРАХ 2016_ОДА. ПРОИГРАЛ ПРАИМЕРИЗ
ДЕМОКРАТИЧЕСКОИ ПАРТИИ ХИППАРИ КЛИНТОН
>
4820 . ЗАДРЦ С ВО
НАСТОЙ'ЁИВОСТЬ
_умвдив говорить нд РАзнБіх языкдх
>
4865 «здльный торчок»
>
5055 »" “
«РЭП- ЭТО ОСМЫСЛЕНИЕ РЕАЛЬНОСТИ»
>


У скрипта явно есть некие проблемы с распознанием «специфического» ВДУДЬ-шрифта. Я вижу решение данной проблемы в доработке файла словаря для OCR и в постобработке текста через PyEnchant.

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

Если Вы можете поспособствовать тому, чтобы Юрий узнал об этом эксперименте, просьба сделать это не откладывая. #habr #vdudictionary ВК, FB.

Спасибо за внимание! Скрипт и пост получились в результате полета фантазии при изучении OpenCV для моего проекта робота по сбору мячей для гольфа.

Вы можете помочь и перевести немного средств на развитие сайта



Комментарии (20):

  1. saipr
    /#19322322 / +1

    Просто и элегантно. И самое главное полезно.

    • webzuweb
      /#19322342

      Спасибо! Я думаю, в целом такой скрипт может быть полезен для распознания вшитых субтитров. Я надеюсь, кому-то он поможет. Я узнаю много нового для себя в процессе написания таких скриптов для удовольствия.

  2. Andronas
    /#19322550 / -1

    проект «Вдудь» не нуждается в представлении
    но видимо не всем, есть еще маргиналы

    • aapazhe
      /#19322746 / +4

      Не видел ни одного выпуска. И не собираюсь смотреть впредь.

      Лучше быть маргиналом, чем жрать дерьмо с транспортёра только потому, что «его едят все».

      • webzuweb
        /#19322832

        Причем здесь это?
        Вы можете смотреть что душе угодно.
        Скрипт о получении текста из видео.

      • lumaxy
        /#19323152

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

        • GoldJee
          /#19323324

          Согласен. Это как с музыкой. У всех свои предпочтения.
          А «жрать с транспортера только потому что едят все» никто и не предлагает. aapazhe, смотрите то, что интересно вам, потому что оно вам интересно.

    • Andronas
      /#19323036

      Таки это была ирония сам этого проекта не видел до сегодняшнего дня. Но отчаянные минусаторы лепят минусы налево и направо из серии «не читал не смотрел но осуждаю» ;)

  3. GoldJee
    /#19323332

    начинает обрабатывать по одному кадру в 5 секунд

    Почему такая низкая производительность? Это из-за железа (Raspberry), языка (Python) или тяжелых алгоритмов распознавания? Можно ли как-то ускорить?

  4. shalm
    /#19323484

    может быть обрабатываются не все кадры, а взятые из видео с интервалом пять секунд?

    • webzuweb
      /#19323848

      Один кадр из 5 секунд.
      И обрабатывается он около 5 сек.
      Raspbery pi 3

  5. lari4
    /#19327742

    Еще бы код был на нормальном питоне. Такое название переменных

    spisoksimvolovpodudalenie
    очень больно видеть

    • webzuweb
      /#19328458

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

      • lari4
        /#19329232

        • Никогда не пишите названия переменных по-русски латиницей (spisoksimvolovpodudalenie, udaleniesimvolov, stroka, etc.), этот же смысл можно же и на английском передать (chars_for_replace, replace_chars, line). И еще про spisoksimvolovpodudalenie, если у Вас объект типа list, не надо в названии указывать то, что это список.
        • Лишняя переменная title, у Вас объект уже храниться в a.title .
        • Для работы с файлами используйте менеджер контекста.
        • У Вас везде используется конкатенация строк, вместо этого используйте либо .format, либо f-string(>= python 3.6).
        • Переменная nameofvideo — название не соответствует содержанию и написание не по PEP8, video_id, как вариант.

        • webzuweb
          /#19329268

          Все по делу, спасибо.
          Стоило ли весь код завернуть в функцию?

          • lari4
            /#19329298

            если в дальнейшем хотите где-то переиспользовать, стоит, и не в одну, а разбить на множество функций.

  6. HeaTTheatR
    /#19327850

    Код, конечно, ужасный! За такой код нужно отрезать пальцы вместе с руками!

    • webzuweb
      /#19328456

      До таких экзекуций я опускаться не буду.
      От Вас в качестве мастер-класса, можно получить разбор основных ошибок?