HLS streaming experiment

HLS

Note: Code written by AI. All experiments done on win10 machine.

Goal: Stream my desktop for the purpose of teaching.
More: Provide a remote user with a link that can be opened in browser (or/and VLC). Don’t bother with sound. Use GPU for video encoding to reduce propeller noise.

python server.py

from http.server import HTTPServer, SimpleHTTPRequestHandler

class CORSHandler(SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        super().end_headers()

port = 8080
server = HTTPServer(('0.0.0.0', port), CORSHandler)
print(f"Serving on http://localhost:{port}")
server.serve_forever()

stream.bat

ffmpeg -f gdigrab -video_size 1920x1080 -framerate 25 -i desktop ^
-c:v h264_nvenc -preset p6 -tune ull ^
-b:v 6000k -maxrate 6000k -bufsize 1200k ^
-g 50 ^
-f hls -hls_time 1 -hls_list_size 3 ^
-hls_flags delete_segments+append_list+omit_endlist ^
-hls_segment_type fmp4 -hls_fmp4_init_filename init.mp4 ^
stream.m3u8
  • Latency may be reduced by using smaller ‘-bufsize’, but the video quality will suffer (at some point very visible jumping).

or/and possibly better

stream_gfxcapture.bat (seems to reduce latency for some reason, in loopback mode i get close to 3s. Note that we are now in Variable-Frame-Rate mode.)

ffmpeg -filter_complex gfxcapture=monitor_idx=0:output_fmt=8bit:max_framerate=50 ^
-c:v h264_nvenc -preset p6 -tune ull ^
-b:v 6000k -maxrate 6000k -bufsize 1200k ^
-g 50 ^
-f hls -hls_time 1 -hls_list_size 3 ^
-hls_flags delete_segments+append_list+omit_endlist ^
-hls_segment_type fmp4 -hls_fmp4_init_filename init.mp4 ^
stream.m3u8

player.htm

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>HLS Stream</title>
  <style>
    body { background: #000; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
    video { width: 80%; height: auto; }
  </style>
</head>
<body>
  <video id="video" controls autoplay muted></video>

  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script>
    const video = document.getElementById('video');
    const hlsUrl = 'stream.m3u8'; // your HLS playlist

    if (Hls.isSupported()) {
      const hls = new Hls({
        // optional low-latency tuning
        liveSyncDurationCount: 3, 
        maxBufferLength: 10
      });
      hls.loadSource(hlsUrl);
      hls.attachMedia(video);
      hls.on(Hls.Events.MANIFEST_PARSED, () => video.play());
    } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
      // Safari native HLS support
      video.src = hlsUrl;
  video.addEventListener('loadedmetadata', () => video.play());
} else {
  alert("HLS not supported in this browser");
}
</script>
</body>
</html>

Notes

Latency is significant (5 - 30s). CPU usage is still high, possibly ffmpeg is doing something weird (-video_size ? Can’t i just select monitor 1 somehow?). Stuff to try. < FIXED, gfxcapture is the king.

There is also (very similar?) DASH standard, where one could use HEVC encoding, but chrome/firefox will not work with that (mpv/vlc should).

Autojump to Zoxide

Install zoxide from the page, the curl command

https://github.com/ajeetdsouza/zoxide
Version in debian 13 is to old to support the import –from command.

Import db from autojump

zoxide import --from=autojump ".local/share/autojump/autojump.txt" --merge

in .zshrc add

# zoxide
eval "$(zoxide init zsh)"

Make sure zoxide is on $PATH, or in .zshrc add

# /home/b/.local/bin for zoxide
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi

Alias j to z

in .bash_aliases or similar file

# autojump to zoxide
alias j='z'

Apt remove autojump, clean autojump entries from .zshrc.

Besides ‘z’ command, there is also ‘zi’ which provides interactive fuzzy search over zoxide history.

Debate: https://news.ycombinator.com/item?id=45342943.

Fart Button in JavaScript (Full Course)

https://www.youtube.com/watch?v=K9V8UA-oJBE

tsoding / Implementing a Fart Button Website

Multipage pdf to series of pngs with transparency

pdftocairo is part of the poppler-utils package.

pdftocairo -png -transp -scale-to 2048 in.pdf out

Larger of width or height will be scaled to 2048px.
Output will be series of png’s, like:

out-01.png
out-02.png
out-03.png
...

Man page.

You Suck at Programming

Creating a PERSISTENT Progress Bar on the Terminal with Bash! v2 Progress Bar

video:
https://www.youtube.com/watch?v=r2rbAvXMcXQ

source:
https://github.com/bahamas10/ysap/blob/main/code/2025-09-03-progress-bar-2/progress-bar

Nice ‘fatal’ function imho:

fatal() {
  echo '[FATAL]' "$@" >&2
  exit 1
}

Why not a bar with higher resolution?

# one block is 8 possible parts, 12.5 % in each
#U+2588	█	Full block                  100  %
#U+2589	▉	Left seven eighths block    87.5 %
#U+258A	▊	Left three quarters block   75   %
#U+258B	▋	Left five eighths block     62.5 %  
#U+258C	▌	Left half block             50   %
#U+258D	▍	Left three eighths block    37.5 %
#U+258E	▎	Left one quarter block      25   %
#U+258F	▏	Left one eighth block       12.5 %

Making Minecraft Spherical

https://www.bowerbyte.com/posts/blocky-planet
https://news.ycombinator.com/item?id=45055205

Quote:

It took me a little over a month to code, during which time I was able to dedicate about 15 hours per week. I did have previous experience with voxels, so the main challenge was just making it spherical. Ironically, it took over twice as long to write/illustrate this blog post.

Pirc

How I went from 500 to 2000 in Chess with THE PIRC DEFENSE

https://www.youtube.com/watch?v=PZDVgiq2q8M
Really neatly executed over the range.