Created
May 17, 2015 22:21
-
-
Save w495/173534c1de5e969cbd7e to your computer and use it in GitHub Desktop.
Простой символьный консольный видео-плеер. Написан с помощью библиотеки PyAV http://mikeboers.github.io/PyAV/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
''' | |
Простой текстовый консольный видео-плеер. | |
Выводит кадры в символьном представлении на стандартный вывод. | |
Поддержки звука нет. | |
Как пользоваться: | |
$> simple-console-video-player.py /путь/до/видео-файла.mp4 | |
''' | |
import sys | |
## | |
## Импортируем библиотеку PyAV (http://mikeboers.github.io/PyAV/). | |
## Библиотека была установлено командой | |
## $> conda install -c danielballan pyav. | |
## | |
import av | |
from av.video.frame import VideoFrame | |
## | |
## Масштаб видео. | |
## | |
SCALE_MEASURE = 0.5 | |
## | |
## Формат видео. | |
## В данном случае оттенки серого цвета от 0 до 2¹⁶ (65536). | |
## | |
FORMAT = 'gray16' | |
FORMAT_GRAY16_SIZE = 65536 | |
## | |
## Представление пикселей с помощью символов псевдографики. | |
## | |
TEXT_PIXEL_LIST = u' .-+#' | |
## | |
## Видео-файл по-умолчанию. | |
## | |
DEFAULT_FILE_NAME = 'video1.mp4' | |
def main(): | |
## Получаем имя видео-файла. | |
video_file_name = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_FILE_NAME | |
## Открываем его как видео-контейнер. | |
video_container = av.open(video_file_name) | |
## Извлекаем пакеты из видео-контейнера — получаем список. | |
packet_list = video_container.demux() | |
## Выполняем для каждого пакета. | |
for packet in packet_list: | |
# Получаем список кадров из пакета. | |
frame_list = packet.decode() | |
## Выполняем для каждого кадра из списка. | |
for frame in frame_list: | |
## Если кадры — это видео | |
## (а могут быть еще аудио, например). | |
if(type(frame) == VideoFrame): | |
new_width = int(SCALE_MEASURE * frame.width) | |
new_height = int(SCALE_MEASURE * frame.height) | |
## Создаем временную кадр-структуру в нужном нам формате. | |
tmp_frame = frame.reformat( | |
width = new_width, | |
height = new_height, | |
format = FORMAT | |
) | |
## Получаем из временного кадра двумерный массив пикселей. | |
nd_array = tmp_frame.to_nd_array() | |
## Печатаем массив точек. | |
for nd_array1 in nd_array: | |
for x in nd_array1: | |
## Рисуем пиксель в консоль без перевода строки. | |
print get_gray16_text_pixel(x), | |
## Строка пикселей кончилась, | |
## делаем перевод строки. | |
print '\n' | |
## Конец кадра рисуем ограничитель | |
print '\n\n' | |
print '==' * (new_width) | |
print '\n\n' | |
print 'Fin!' | |
def get_gray16_text_pixel(pixel): | |
''' | |
Возвращает символ-пиксель, который соответствует, | |
настоящему пикселю-числу формата «gray16». | |
''' | |
## Получаем размер диапазона оттенков, | |
## который будет представлен одним нашим текстовым «пикселем» | |
step = FORMAT_GRAY16_SIZE / len(TEXT_PIXEL_LIST) | |
## Вычисляем номер нашего текстового пикселя. | |
text_pixel_index = pixel / step | |
## Возвращаем символ из списка текстовых «пикселей» | |
return TEXT_PIXEL_LIST[text_pixel_index] | |
if (__name__ == '__main__'): | |
main() | |
Выдает ошибку:
Traceback (most recent call last):
File "./simple-console-video-player.py", line 104, in <module>
main()
File "./simple-console-video-player.py", line 74, in main
nd_array = tmp_frame.to_nd_array()
File "av/video/frame.pyx", line 259, in av.video.frame.VideoFrame.to_nd_array
ValueError: Cannot conveniently get numpy array from gray16le format
Как решить?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Для сравнения аналогичный пример на Go (Golang):
https://gist.github.com/w495/1a40a09bfe50b8841602