Initial commit
Alpine 3.24 aarch64 Success
Arch Linux AUR Scripts failed
Alpine 3.24 Success

This commit is contained in:
2026-07-31 16:39:39 +02:00
commit 5c56c50fcd
9 changed files with 1646 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
BasedOnStyle: LLVM
ColumnLimit: 80
IndentWidth: 4
TabWidth: 4
AccessModifierOffset: -4
UseTab: ForContinuationAndIndentation
SpaceAfterCStyleCast: true
AlignAfterOpenBracket: DontAlign
AlignEscapedNewlines: DontAlign
AlignOperands: DontAlign
AlignConsecutiveMacros: Consecutive
BreakBeforeTernaryOperators: true
SpacesBeforeTrailingComments: 2
WhitespaceSensitiveMacros: ['XX']
+1
View File
@@ -0,0 +1 @@
/build*/
+71
View File
@@ -0,0 +1,71 @@
cmake_minimum_required(VERSION 3.13)
project(asciicast2webp VERSION 0.1 LANGUAGES CXX)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBRARIES REQUIRED
vterm cairo libwebp libwebpmux libjq oniguruma)
pkg_search_module(TERMINFO REQUIRED tinfo ncursesw)
add_executable(${PROJECT_NAME} ${PROJECT_NAME}.cpp)
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
target_compile_options(${PROJECT_NAME} PRIVATE
-Wall -Wextra -Wpedantic -Wconversion -Wshadow
${LIBRARIES_CFLAGS_OTHER} ${TERMINFO_CFLAGS_OTHER})
target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE
${LIBRARIES_INCLUDE_DIRS} ${TERMINFO_INCLUDE_DIRS})
target_link_directories(${PROJECT_NAME} PRIVATE
${LIBRARIES_STATIC_LIBRARY_DIRS} ${TERMINFO_STATIC_LIBRARY_DIRS})
target_link_options(${PROJECT_NAME} PRIVATE
${LIBRARIES_STATIC_LDFLAGS_OTHER} ${TERMINFO_STATIC_LDFLAGS_OTHER})
target_link_libraries(${PROJECT_NAME} PRIVATE
${LIBRARIES_STATIC_LIBRARIES} ${TERMINFO_STATIC_LIBRARIES})
include(CTest)
if(BUILD_TESTING)
add_test(
NAME fixture
COMMAND ${CMAKE_COMMAND}
-DPLAYER=$<TARGET_FILE:${PROJECT_NAME}>
-DCAST=${PROJECT_SOURCE_DIR}/tests/fixture.cast
-DOUTPUT=${PROJECT_BINARY_DIR}/fixture.webp
-P ${PROJECT_SOURCE_DIR}/tests/fixture.cmake
)
add_test(
NAME fixture-drop-short
COMMAND ${CMAKE_COMMAND}
-DPLAYER=$<TARGET_FILE:${PROJECT_NAME}>
-DCAST=${PROJECT_SOURCE_DIR}/tests/fixture.cast
-DOUTPUT=${PROJECT_BINARY_DIR}/fixture-drop-short.webp
-DDROP_SHORT=ON
-P ${PROJECT_SOURCE_DIR}/tests/fixture.cmake
)
add_test(
NAME fixture-v3
COMMAND ${CMAKE_COMMAND}
-DPLAYER=$<TARGET_FILE:${PROJECT_NAME}>
-DCAST=${PROJECT_SOURCE_DIR}/tests/fixture-v3.cast
-DOUTPUT=${PROJECT_BINARY_DIR}/fixture-v3.webp
-P ${PROJECT_SOURCE_DIR}/tests/fixture.cmake
)
endif()
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Directory navigator")
set(CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
set(CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set(CPACK_GENERATOR "TGZ")
set(CPACK_PACKAGE_FILE_NAME
"${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
set(CPACK_SET_DESTDIR TRUE)
include(CPack)
+12
View File
@@ -0,0 +1,12 @@
Copyright (c) 2026, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+87
View File
@@ -0,0 +1,87 @@
asciicast2webp
==============
:compact-option:
'asciicast2webp' converts asciicast v2 and v3 terminal recordings into
animated WebP files. If possible, it preserves terminal colours,
and *renders captured keypresses* in roughly the Emacs key notation.
The old asciicast v2 format cannot store the colour theme,
in which case it defaults to black on white.
Example output can be seen at https://git.janouch.name/p/sdn
Background
----------
First, I thought something as simple would already exist.
But there's basically only _agg_, which doesn't care about keypresses,
and it uses an inefficient file format.
Second, I thought this would be reasonably doable in something other than C++.
Meanwhile, all the good important libraries have a C API.
Text rendering could still see some improvements, but I've already spent
enough time on this project for now.
Packages
--------
Regular releases are sporadic. git master should be stable enough.
https://janouch.name/cd[Static Linux builds can be found here],
simply place the binary somewhere in your PATH.
Building
--------
Build-only dependencies: CMake, a C++20 compiler, pkg-config +
Runtime dependencies: libvterm, Cairo, libwebp, libwebpmux, libjq,
and a terminfo library (tinfo or ncursesw)
$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
$ cmake --build build
Usage
-----
Pass an input cast and an output WebP path:
$ asciicast2webp [OPTION...] recording.cast recording.webp
Options
-------
`--font NAME`, `--size POINTS`::
Choose the terminal font and size.
The defaults are `monospace` and 10 points.
`--border PIXELS`::
Add space around the terminal.
`--key-timeout SECONDS`::
Control how long captured keypresses remain visible. Use zero to hide them.
`--top EM`, `--left EM`::
Position the keypress badge. Positive values measure from the top or left;
negative values measure from the bottom or right.
`--preset LEVEL`::
Choose the lossless WebP compression effort from 0 through 9.
The default is 6; higher values take longer.
`--near-lossless QUALITY`::
Enable near-lossless preprocessing from 0 through 100. The default, 100,
leaves it disabled.
`--duration-min MILLISECONDS`::
Set the shortest encoded frame duration. The default of 11 milliseconds
avoids unreliable playback of very short frames in browsers. Use zero to
preserve the recording's rounded timing.
`--drop-short`::
Drop frames shorter than `--duration-min` instead of lengthening them.
Run with `--help` for the complete command-line summary.
Contributing and Support
------------------------
Use https://git.janouch.name/p/asciicast2webp to report any bugs,
request features, or submit pull requests. `git send-email` is tolerated.
If you want to discuss the project, feel free to join me
at ircs://irc.janouch.name, channel #dev.
Bitcoin donations are accepted at: 12r5uEWEgcHC46xd64tt3hHt9EUvYYDHe9
License
-------
This software is released under the terms of the 0BSD license, the text of which
is included within the package along with the list of authors.
+1414
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
{"version":3,"term":{"cols":12,"rows":3,"type":"xterm-256color","theme":{"fg":"#d0d0d0","bg":"#212121","palette":"#151515:#ac4142:#7e8e50:#e5b567:#6c99bb:#9f4e85:#7dd6cf:#d0d0d0:#505050:#ac4142:#7e8e50:#e5b567:#6c99bb:#9f4e85:#7dd6cf:#f5f5f5"}},"idle_time_limit":0.1}
# v3 uses relative event intervals and permits comments
[0.0,"o","hello"]
[0.005,"o","\rworld"]
[0.005,"i","x"]
[0.01,"o","\n界\u001b[D"]
[0.005,"o","\u001b[D"]
[0.025,"x","0"]
+6
View File
@@ -0,0 +1,6 @@
{"version":2,"width":12,"height":3,"duration":0.05,"env":{"TERM":"xterm-256color"}}
[0.0,"o","hello"]
[0.005,"o","\rworld"]
[0.01,"i","x"]
[0.02,"o","\n界\u001b[D"]
[0.025,"o","\u001b[D"]
+33
View File
@@ -0,0 +1,33 @@
file(REMOVE "${OUTPUT}")
if(DROP_SHORT)
set(options --drop-short)
set(expected "2 frames, 0.05 s")
else()
set(options)
set(expected "4 frames, 0.062 s")
endif()
execute_process(
COMMAND "${PLAYER}" ${options} "${CAST}" "${OUTPUT}"
RESULT_VARIABLE result
OUTPUT_VARIABLE stdout
ERROR_VARIABLE stderr
)
if(NOT result EQUAL 0)
message(FATAL_ERROR "player failed (${result}): ${stderr}")
endif()
if(NOT stdout MATCHES "${expected}")
message(FATAL_ERROR "unexpected player summary: ${stdout}")
endif()
file(SIZE "${OUTPUT}" size)
if(size LESS 12)
message(FATAL_ERROR "fixture WebP is unexpectedly small (${size} bytes)")
endif()
file(READ "${OUTPUT}" signature LIMIT 12 HEX)
string(SUBSTRING "${signature}" 0 8 riff)
string(SUBSTRING "${signature}" 16 8 webp)
if(NOT riff STREQUAL "52494646" OR NOT webp STREQUAL "57454250")
message(FATAL_ERROR "fixture output is not a RIFF/WebP file")
endif()