-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathINTERNALS
More file actions
244 lines (181 loc) · 10.3 KB
/
Copy pathINTERNALS
File metadata and controls
244 lines (181 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
TODO: put version in excectuable name, both in local makefile and also gh action
also update docs/readme about availability of static binaries
and possibly decrement alpine rust version for the sake of compatiblity
also update chafa-sys test for newer chafa version
also make semi-automated deploy checklist, prompting me about container build, version number, style, steps to using github, etc
essentially a pre-release checklist, like from my portfolio repo
___
vic depends on ffmpeg and chafa
vic makes ffmpeg calls, assuming ffmpeg is on $PATH:
- main::get_ffprobe_video_metadata() calls `ffprobe` (a sibling of ffmpeg) to get video dimensions and framerate
- main::FrameIterator calls ffmpeg to decode a video file into rgb bytes
- main::main() calls ffmpeg to cut the video into segments (if any segments were made)
calling ffmpeg process on $PATH seemed easier than trying to link ffmpeg libraries
one less build step
not to mention potential license conflicts
ffmpeg performance still seems fine
hopefully there's no downsides
___
builds
chafa bindings crate (with chafa-sys subcrate) details the build instructions and notes
notes should be at:
https://github.com/wong-justin/chafa-rust/blob/master/INTERNALS
and also the readme
the build instructions trickle down to this consumer project
in summary:
the easier way to build is to link chafa dynamically, meaning chafa (+glib dependency) should already be installed on the user's system.
the chafa binary is not needed here, but rather the development libraries and header files.
nothing in place to check specific chafa versions; i just went with the latest chafa version at the time, and hopefully it will work for everyone.
static builds involve several new challenges, mostly glib
glib like a third-party stdlib for C, including threading implementations, string handling, etc
glib is chafa's only (non-libc?) dependency
building and/or statically linking glib is nontrivial
thanks to mmulet's comment (https://github.com/wong-justin/vic/issues/1#issuecomment-3658269697),
i was able to build vic on alpine with statically linked chafa and glib.
(and apparently alpine's musl libc is better for static linking than the more common gnu libc)
i needed extra commands to make it work:
apk add musl-dev, appending -lgcc to $RUSTFLAGS, and telling rustc to look for libintl
gh action can run dockerfile and release the resulting binary
twould be nice to have diff dockerfiles for different platforms (windows, macos), but that will take some extra effort
other nice-to-haves: sha256 binary checksum for users' peace of mind?
TIL most executable downloads, incl zip files, often lose their unix permission metadata somewhere along the way
thankfully .tar.gz files preserve the +x permission
hpj says it would be good to depend on glibc rather than a kernel ABI because the glibc ABI is more stable, and then you could `nm vic | grep GLIBC` to see the latest glibc version required (and use that glibc release year as an estimate of the oldest supported linux-glibc-<arch>)
https://github.com/wong-justin/vic/issues/1#issuecomment-3699068618
another way to build statically, maybe:
https://lobste.rs/c/c42stj
https://gamesbymason.com/blog/2025/statically-linking-pipewire/
also tools to investigate:
objdump -p vic
readelf -d vic
which are kinda like ldd vic
https://ruvi-d.medium.com/linux-binary-compatibility-explained-at-5-levels-of-difficulty-ffeab6235fc8
https://miro.medium.com/v2/resize:fit:1400/format:webp/1*sNDz6x1Z9jt8F9WtiSYUDA.png
compare earliest supported linux kernel of executable vs currently running linux kernel:
`file vic` or `readelf n vic` (GNU/Linux 4.4.0)
uname -r (6.18.2 on my personal machine)
then compare earliest supported glibc to currently running glibc:
...
to link an updated library at runtime (like when your system has an outdated library depdencny and your executable won't run):
LD_LIBRARY_PATH=/tmp/libthing-updated-ver/ ./my-executable
and maybe to link updated glibc at runtime?:
/tmp/my-updated-ld-linux-x86-64.so.2 --library-path /tmp/my-updated-glibcthings? ./my-executable
___
src/tui.rs is a generic MVU TUI setup
(model, view, update for a text-based UI)
(essentially the elm architecture)
requires functions of type:
init -> result<model, error>
view (model, stderr) -> (draws on stderr, returns nothing)
update (model, event) -> continue/finish/failed
uses crossterm crate for a standardized API for terminal emulator communication
current, naive event loop (currently tick every 16ms):
frequently polling the terminal for events like keypresses or resizes
responding to any events received
drawing new frames when appropriate (like ~33ms for 30fps videos) (or after a keypress)
no multithreaded/async event loop yet
all TUI output is written to stderr on the alternate tty buffer
(stdout is reserved for potential messages after app shutdown, i.e. `vic video.mp4 --dry-run`)
___
src/main.rs::FrameIterator is where ffmpeg and chafa meet
chafa is initialized with config like input and output size
each frame, ffmpeg decodes video into rgb bytes
chafa takes rgb bytes and returns a string of ansi colors and unicode blocks, like "[0m[38;2;254;0;0m█[0m", that will be sent to the terminal
src/main.rs::Model contains app state
including config like video dimensions
and also state like current frame number and the list of timestamps (called markers)
src/main.rs::update() is a big match statement handling events and keypresses
keypresses so far are just for moving to different parts of the video and making/deleting markers
___
demo is scripted in Makefile::demo
uses a neovim :terminal session and some lua to show keypresses, taken from the Showkeys plugin
then screencap with something like obs, probably uvx obs-cli
to get a reproducible static image demo, consider
```
vic ~/test/test.mp4 2>&1 | tee ~/test/vicscreenoutput
# print 2500 or however many lines of screen output it took to create the desired screen
cat ~/test/vicscreenoutput | head -2500 ; printf '\n\n\n\n\n\n\n\n\n'
```
___
feature ideas:
zoomable scrubber
https://img.ly/blog/designing-a-timeline-for-mobile-video-editing/
rust audio playback?
https://github.com/RustAudio/rodio
UI mockup ideas:
┌─────────┬───v────────────────────────┐
└─────────┴────────────────────────────┘
segment 2 of 2 help?
┌─┐
│ │
└─┘
────────────────────────────────────────
1:30 / 2:45 playing x1.0
>█████████████████████▋ <
> . .. | . . . : . <
* 2:01.521
2:02.107 8/10
────────────────────────────────────────
0:12 / 9:56 playing
▁▁▁▁▁ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
▎▎▎ │ 🮇
▔▔▔▔▔ ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
segment 3 of 3 help?
___
lesser priorities:
TODO: use chafa::canvas.print_rows() so i dont have to undo line work
TODO: replace all .ok_or(format!(...)) with .ok_or_else(|| format!(...))
see: https://medium.com/@techhara/rust-tip-and-trick-2-5a92641191f6
TODO: use generic Pathlike P instead of filepath: String
and figure out generic type signatures everywhere
___
misc notes:
- internally, chafa represents each char as 8x8 bitmap.
so a canvas of 1 row of 2 chars has 8x8 internal resolution
see: chafa/internal/chafa-symbols-block.h
- a random data point on my older windows machine, i5 processor:
ffmpeg decoding 60fps 180p video into raw frames into /dev/null takes ~3.5 mins, with 1.5GB/sec throughput, and results in 115GB of raw pixel frame output
- looping read_exact() 30x seems faster than reading ffmpeg output stream into a buffer 30x as large. idk why.
- not sure how to seek backwards except for caching frames/data after reading it
- "Writing more than a pipe buffer’s worth of input to stdin without also reading stdout and stderr at the same time may cause a deadlock."
- maybe framereading process can keep reading as long as possible, while display process will only request frames less frequently. also giving the decoding process a head start and caching first few frames might help it feel smoother
- making a new vec buffer each render call seems nearly as fast as using one permanently assigned vec, surprisingly
- usize is meant for referencing memory locations. so dont use it for typical application properties.
- can't declare Box[] of large size because stack isnt that big.
instead, declare vec[] and then .into_boxed_slice() will avoid initializing on stack
perhaps learn more from:
https://github.com/jart/hiptext/blob/master/src/movie.cc
https://github.com/zmwangx/rust-ffmpeg/blob/master/examples/dump-frames.rs
https://github.com/maxcurzi/tplay/blob/main/src/pipeline/frames.rs
https://gist.github.com/AndreaCatania/2b708750ef62171f51c7038e99676822
https://github.com/oddity-ai/video-rs
https://medium.com/init-deep-dive/rust-video-frame-extraction-speed-comparison-4d33fcc99405
chafa_src/tools/chafa/chafa.c::line2963+ while (is_animation)
libavformat
libavutil
to learn more about video formats:
https://gist.github.com/arch1t3cht/b5b9552633567fa7658deee5aec60453/
maybe replace pico-args with:
https://crates.io/crates/bpaf/0.9.20
___
PRE-WORK RITUAL
taken from:
https://pgadey.ca/notes/writing-ritual/
- am i cozy?
- do i have water?
- is the source code open?
- do i have a notebook nearby?
- is my phone muted / far away?
- do i have an entry point / is the work log updated?
- did i listen to one of the songs?
https://pgadey.ca/share/present-time.mp3
https://pgadey.ca/share/dwelling.mp3
- did i freewrite/warmup for a couple minutes?
magic project thesis:
??
work log: date, time -- duration. -- entry point -- what got done?
- oct 16, 9:30am -- ?? mins. -- task: work on adding UI thread and processing thread
- ??, next entry point: ??
refactor: more accurate makefile command names
"make install" usually means put compiled program on system path
"make download-something" is more clear about