Initial commit
This commit is contained in:
@@ -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']
|
||||
@@ -0,0 +1 @@
|
||||
/build*/
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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"]
|
||||
@@ -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"]
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user