Думаю, все помнят telnet версию SW:New Hope. В связи с блокировкой PornHub'а, возникла идея сделать что-то подобное с их видео. Вооружимся питоном и попробуем реализовать задумку.
Тот самый StarWars.
1. Добыча контента.
У порнхаба есть довольно внятное апи, поэтому воспользуемся им. Описание находится здесь(к сожалению, придется зарегистрироваться). С его помощью можно вытянуть ссылки на страницы с видео, но далее нам все же придется копаться в html.
К счастью, нужная ссылка легко выдирается с помощью регулярки
def getVideoUrl(pageUrl):
response = urllib2.urlopen(pageUrl)
content = response.read()
videoRegex = re.compile(r'player_quality_d+ps+=s+'(?P<url>.+?';)')
m = videoRegex.search(content)
url = m.group('url')
return url
Что еще стоит отметить на данном этапе: pornhub периодически возвращает 403 при попытке скачать видео, решается эта проблема сменой User-Agent.
2. Конвертация.
Теперь нам нужно сконвертировать видео в ASCII графику. Для этого воспользуемся OpenCV.
Алгоритм крайне простой:
- RGB -> Grayscale
- Downscale до нужного разрешения
- Преобразование пикселей в символ
Так как мы собираемся выводить результат в telnet, возьмем за основу разрешение 80х24:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
res = cv2.resize(gray, (80, 24))
Думаю, следует пояснить зачем мы конвертируем в grayscale: нас интересует только информация об освещенности, ее можно получить двумя способами — сконвертировать в YUV и вытащить Y канал или сконвертировать в grayscale.
Далее нам просто нужно проитерироваться по пикселям и сконвертировать полученные значения в символы:
def lumToChar(l):
result = '@'
if l >= 230.0:
result = ' '
elif l >= 200.0:
result = '.'
elif l >= 180.0:
result = '*'
elif l >= 160.0:
result = ':'
elif l >= 130.0:
result = 'o'
elif l >= 100.0:
result = '&'
elif l >= 70.0:
result = '8'
elif l >= 50.0:
result = '#'
return result
3. Вывод в telnet.
Все, что нам осталось сделать — поднять tcp сервер и при подключении стримить туда наше видео. Однако, тут есть загвоздка: каждый кадр нужно очищать буффер. Для этого просто посылаем клиенту escape-последовательность
escapeSeq = '33[2J'
Угадайте, что это.
4. Заключение.
Q: Зачем?
A: Было свободное время.
Q: Где можно пощупать результаты?
A: telnet 185.146.170.134 9002
Автор: Filippok