glyphcast
glyphcast
English version · Песочница · Хаб

Опенинг One Piece в режиме Брайля, 180 колонок.
Видео цветными символами. Полноценный плеер для браузера: управление, настройки, субтитры, горячие клавиши, картинка в картинке и полный экран, а каждый кадр перерисовывается символами шейдером WebGL2. Сервер может присылать вместо видео сами символьные кадры, и браузер получает компактный поток .gcast, а не исходное видео. Тот же поток играет и в терминале.
npm install glyphcast
<script type="module">import 'glyphcast/element';</script>
<glyph-player src="movie.mp4" cols="160"></glyph-player>
<glyph-player src="movie.gcast" audio="movie.m4a" subtitles="movie.vtt"></glyph-player>
<glyph-player youtube="https://youtu.be/…" server="http://127.0.0.1:8787"></glyph-player>
Без сборщика: import 'https://cdn.jsdelivr.net/npm/glyphcast@1/dist/element.js/+esm'.
Где играет
| 🌐 Браузер | <glyph-player>, React, Vue |
WebGL2, управление, субтитры, выбор качества |
| 💻 Терминал | glc play movie.gcast |
24-битный цвет, звук через ffplay, те же клавиши |
| 🪟 Windows | glc.exe |
нативный, меньше 1 МБ, звук внутри, без Node |
| 📡 Telnet | glc telnet movie.gcast |
смотреть может кто угодно: telnet host 2323, без установки |
| 🦀 Rust | крейт glyphcast |
кодер и декодер, байт в байт как JS, без зависимостей |
glc.exe
Консольный плеер для Windows одним файлом меньше 1 МБ: без Node и ffmpeg, со звуком и хабом. Скачайте из Releases, запустите двойным щелчком для меню хаба или перетащите на него .gcast:
glc.exe movie.gcast # файл
glc.exe hub:<id> # видео из хаба
glc.exe --lang ru # интерфейс на русском
Telnet
glc telnet movie.gcast --port 2323 # затем с любой машины: telnet <host> 2323
Каждое подключение получает свой плеер с перемоткой и режимами. Звука по telnet нет, у зрителя нужен терминал с 24-битным цветом (Windows Terminal, iTerm2, большинство терминалов Linux).
Rust
[dependencies]
glyphcast = "1"
use glyphcast::format::{decode_chunk, Reader};
let mut reader = Reader::new();
reader.push(&std::fs::read("movie.gcast")?)?;
let info = reader.info.unwrap();
for chunk in &reader.chunks {
for frame in decode_chunk(&info, &chunk.data)? {
// frame.rgb: цвет клетки, frame.masks: её точки Брайля 2×4
}
}
Крейт пишет те же файлы байт в байт, что и JS-кодер, примерно в 3,5 раза быстрее. Подробнее в native/glyphcast.
Плеер
<glyph-player> играет видео, камеру, локальные файлы и потоки .gcast. Внутри: воспроизведение и пауза, ±10 секунд, полоса перемотки с загруженной частью и подсказкой времени, громкость, скорость, картинка в картинке (через Document PiP весь плеер целиком, где браузер это умеет, иначе только изображение), полный экран и меню настроек: ширина сетки, способ отрисовки (символы, точки Брайля или растр), набор символов, цвет, насыщенность, автоуровни, контуры и кинескоп. С контурами клетки на границах предметов рисуются символами - / | \ по направлению границы, а кинескоп добавляет строки развёртки, виньетку и свечение. Во время воспроизведения панель прячется.
| Атрибут | |
|---|---|
src |
Ссылка на видео или файл .gcast |
poster |
Картинка, которая видна до первого кадра |
audio |
Звук для файла .gcast |
youtube, file, server |
Поток через glyphcast serve (см. ниже) |
subtitles |
Субтитры WebVTT или SRT, рисуются той же сеткой символов |
cols |
Ширина сетки в символах, по умолчанию 160 |
glyphs |
Символы от тёмного к светлому, по умолчанию ' .:-=+*#%@' |
tint |
Один цвет для всех символов, например #33ff66 |
boost |
Насыщенность, по умолчанию 1.3 |
autolevels |
false выключает подстройку яркости и контраста |
mode |
glyphs, braille или halftone |
edges, crt |
Контуры и вид кинескопа |
sharp |
false выключает чёткость ×2 (апскейл по границам) |
smooth |
false выключает плавность (промежуточные кадры по движению блоков) |
fill |
Подсветка фона клетки её цветом, от 0 до 1, по умолчанию 0.25 |
autoplay, muted, loop |
Как у <video> |
Клавиши: пробел или K пауза, ←/→ 5 с, J/L 10 с, ↑/↓ громкость, M звук, F полный экран, P картинка в картинке, 0–9 переход. Оформление меняется через --accent и --radius; element.load(файлПотокИлиСсылка) и element.player дают управление из кода.
React и Vue
import { GlyphPlayer } from 'glyphcast/react';
<GlyphPlayer src="/movie.gcast" poster="/movie.jpg" mode="braille" onReady={(player) => player.play()} />
<script setup>
import { GlyphPlayer } from 'glyphcast/vue';
</script>
<template>
<GlyphPlayer src="/movie.gcast" poster="/movie.jpg" mode="braille" @ended="next" />
</template>
Пропсы те же, что атрибуты (autoPlay, autoLevels в camelCase), плюс события play, pause, ended, timeupdate, error и ready с движком. Элемент подгружается после монтирования, поэтому обёртки работают и с серверным рендерингом.
Без интерфейса тот же движок называется GlyphPlayer и повторяет API медиаэлемента: load, play, pause, seek, currentTime, duration, volume, muted, playbackRate, configure(look), setCaptions(текстИлиСсылка) и привычные события.
Символы вместо видео
При 160 колонках кадр состоит примерно из девяти тысяч цветных клеток, это намного меньше кадра видео. .gcast хранит у каждой клетки яркость (6 бит), цвет один на квадрат 2×2 клетки (как 4:2:0 в видео), а с --detail ещё и узор из 2×4 точек у клеток с резкими краями. Сетка нарезана на блоки 8×4: блок предсказывается из прошлого кадра со сдвигом с точностью до точки или из соседей в том же кадре, и передаётся только то, что предсказание не угадало. Всё кодируется адаптивным арифметическим кодером с контекстами (узоры — точка за точкой по соседям, как в JBIG2), поэтому формату не нужен архиватор общего назначения, а декодер маленький. Куски примерно по две секунды начинаются с точного опорного кадра, новая сцена начинает новый кусок. Формат полностью описан в FORMAT.md и заморожен с версии 1.0: все следующие версии его играют. Звук можно вшить прямо в .gcast: он идёт перед кадрами, плеер достаёт его и ведёт по нему время. В песочнице есть конвертер, который делает .gcast из вашего видео прямо в браузере (кодирование идёт в Web Worker) и показывает, во сколько раз файл стал меньше, а рядом готовую команду для консоли. Целые фильмы лучше конвертировать в консоли: браузер не удержит в памяти их звук. В конце файла лежит индекс кусков: плеер читает его range-запросом и при перемотке сразу качает нужное место, не дожидаясь загрузки всего файла. Формат потоковый: у кусков есть длина, поэтому плеер начинает с первого же куска, а сервер может выдавать их на лету.
npx glyphcast encode movie.mp4 --cols 180 --embed --poster # один файл со звуком Opus внутри и постер movie.jpg
npx glyphcast encode movie.mp4 --detail # узор 2×4 точек из исходника: чёткий текст в режиме Брайля, файл больше примерно на 50%
npx glyphcast encode *.mp4 --embed # несколько видео подряд, с прогрессом и оставшимся временем
npx glyphcast encode movie.mp4 --cols 180 --audio movie.m4a # звук отдельным файлом
npx glyphcast hub # видео в gcast hub, смотреть: npx glyphcast play hub:имя
npx glyphcast play movie.gcast # в терминале: пробел пауза, ←/→ перемотка, M отрисовка, G символы, C цвет, [ ] насыщенность, B фон, Q выход
npx glyphcast serve --dir ./videos # живые потоки
npx glyphcast micro movie.mp4 --cols 180 # крошечное H.264 размером с сетку
glyphcast serve превращает ссылки на YouTube (через yt-dlp) и видео из папки --dir в живые потоки .gcast с отдельным звуком Opus, перематывает, перезапуская поток с нужной секунды, и отдаёт готовые файлы с поддержкой range-запросов. Слушает только 127.0.0.1. Браузер сам не может читать кадры YouTube, поэтому YouTube работает именно через этот сервер. glyphcast play принимает и ссылку на такой поток, так что YouTube можно смотреть прямо в терминале.
Минута фильма, только картинка, 24 к/с:
| Что отправляется | Размер | Битрейт |
|---|---|---|
| Исходник, 1280×544 H.264 | 4,20 МБ | 587 кбит/с |
.gcast 0.26 (формат 5), 180 колонок, --detail |
1,55 МБ | 217 кбит/с |
.gcast 1.0 (формат 6), 180 колонок, --detail |
0,98 МБ | 137 кбит/с |
.gcast 1.0, 180 колонок |
0,52 МБ | 73 кбит/с |
.gcast 1.0, 120 колонок, --detail |
0,50 МБ | 69 кбит/с |
| Микровидео, 180 колонок H.264 | 0,29 МБ | 41 кбит/с |
Файлы формата 6 на 32–39% меньше формата 5 на фильмах, мультфильмах и записях экрана и при этом ближе к исходнику (SSIM картинки из точек выше на 0,03–0,07). Размер потока зависит от сетки и движения в кадре, а не от разрешения исходника. Микровидео размером с сетку всё равно меньше: видеокодеки десятилетиями оттачивали под пиксели. .gcast хранит то, что рисуется, — клетки и узоры их точек, поэтому ему не нужен видеодекодер, он одинаково играет в браузере и в текстовом терминале, сохраняет тонкие линии и текст точками, и его можно генерировать или править покадрово. В Node модуль glyphcast/node даёт encodeVideo, encodeMicroVideo, extractAudio и serve, а Encoder собирает поток из сырых кадров любого источника.
Хаб
gcast hub хранит видео в .gcast и показывает их в браузере. Те же видео играют в консоли:
npx glyphcast hub # список и поиск
npx glyphcast play hub:<имя> # смотреть со звуком, паузой и перемоткой
npx glyphcast login # вход через Google (в браузере), нужен для загрузки
npx glyphcast publish movie.mp4 --title "Название" # закодировать три сетки со звуком и загрузить
Загрузка требует входа через Google — на сайте или командой glc login. Новое видео сразу открывается по ссылке, а в общий список попадает после проверки. Правила и конфиденциальность.
Лицензия
Mozilla Public License 2.0 (см. LICENSE и NOTICE): изменения в файлах glyphcast остаются открытыми, ваш код вокруг может быть закрытым. Версии до 0.20.13 вышли под MIT, 0.21.0–0.21.3 — под Apache 2.0.
Related Packages
Matrix-style glyph rain with cursor stir and drop-head lighting for React and Vu...
Version History
| Version | Released | License |
|---|---|---|
| 1.5.3 | MPL-2.0 | |
| 1.5.2 | MPL-2.0 | |
| 1.5.1 | MPL-2.0 | |
| 1.4.0 | MPL-2.0 | |
| 1.3.0 | MPL-2.0 | |
| 1.2.0 | MPL-2.0 | |
| 1.1.0 | MPL-2.0 | |
| 1.0.2 | MPL-2.0 | |
| 1.0.1 | MPL-2.0 | |
| 1.0.0 | MPL-2.0 | |
| 0.26.0 | MPL-2.0 | |
| 0.25.0 | MPL-2.0 | |
| 0.24.0 | MPL-2.0 | |
| 0.23.0 | MPL-2.0 | |
| 0.22.1 | MPL-2.0 | |
| 0.22.0 | MPL-2.0 | |
| 0.21.3 | Apache-2.0 | |
| 0.21.2 | Apache-2.0 | |
| 0.21.1 | Apache-2.0 | |
| 0.21.0 | Apache-2.0 | |
| 0.20.13 | MIT | |
| 0.20.12 | MIT | |
| 0.20.11 | MIT | |
| 0.20.10 | MIT | |
| 0.20.9 | MIT | |
| 0.20.8 | MIT | |
| 0.20.7 | MIT | |
| 0.20.6 | MIT | |
| 0.20.5 | MIT | |
| 0.20.3 | MIT |
Showing the latest 30 of 79. See every release on npm
Pre-releases (1)
| Version | Released | License |
|---|---|---|
| 0.0.0-stage |