TTY, Linux Framebuffer, EGLFS and SDL - Without the weight of Xorg or Wayland

2025-09-13

Right now I'm using w3m, and lynx. Lynx has a retarded configuration so I have to change it a little bit:

Some configurations are not save unless you edit the /etc/lynx.cfg

set Advanced mode (user_mode=ADVANCED) to get more screen real-estate

Make navigation easier

Make images easier to work with

Currently, I’m only using EGLFS with ttyd, I start my browser with the following script:

EXTERNAL:http:w3m %s:TRUE EXTERNAL:http:cha %s:TRUE EXTERNAL:http:mpv %s:TRUE EXTERNAL:http:netsurf-fb -f sdl -w 1366 -h 768 %s:TRUE EXTERNAL:http:falkon %s:TRUE EXTERNAL:http:angelfish %s:TRUE

#!/bin/bash
sudo chmod 666 /dev/input/event*

ttyd --port 2020 --writable fish & 

falkon "http://localhost:2020"

And in .config/fish/config.fish I had:

if test -z "$TMUX" -a $XDG_VTNR = 1
  tmux attach || exec tmux new-session
end
export QT_QPA_PLATFORM=eglfs  
export XKB_DEFAULT_LAYOUT=es
set -U fish_greeting
export BROWSER=w3m


1. TTY Environment Setup

For efficient management of your terminals and processes, it is essential to use a terminal multiplexer.

if test -z "$TMUX" -a $XDG_VTNR = 1
  tmux attach || exec tmux new-session
end

This will automatically start tmux in the tty number 1 (a terminal multiplexer similar to tmux).
Alternatively, you can use dvtm.

2. Web Browsing from TTY

3. Multimedia Viewing: Images, PDFs, and Videos

My /etc/mpv/mpv.conf:

$ cat /etc/mpv/mpv.conf  
--profile=fast  
--sub-auto=all  
--vo=drm
--ytdl-raw-options="format=bestvideo[height<=?360]+bestaudio/best[height<=?360]/bestvideo[height<=?480]+bestaudio/best[height<=?480],write-auto-sub=,sub-lang=[es,en,ru],write-sub="  
--volume-max=600  
#--save-position-on-quit  
#--untimed  
#--profile=low-latency  
--mute=yes  

My /etc/yt-dlp.conf:

$ cat /etc/yt-dlp.conf  
--format=233+230  
--write-auto-sub  
--write-sub  
--sub-lang=en  
#--cookies-from-browser firefox  

Important: If you use mpv for videos, run it outside tmux; otherwise, you won’t be able to switch between other TTYs.

4. Using Lightweight Graphical Applications in TTY (FrameBuffer: eglfs and linuxfb)

#export QTWEBENGINE_CHROMIUM_FLAGS="--ignore-gpu-blacklist --disable-gpu"
export QTWEBENGINE_CHROMIUM_FLAGS="--ignore-gpu-blacklist"
export QT_QPA_PLATFORM=eglfs  

Then, start your Qt application (e.g., qutebrowser).

export QT_QPA_PLATFORM=linuxfb:size=1000x1000  

To run some applications that normally require a graphical server (like graphical web browsers), you can run it using linuxfb or eglfs.

Always open Qt apps inside a Terminal Multiplexer, otherwise when the application freezes your entire machine will freeze and you won’t be able to use Control+C.

In some Linux distributions, you need to run the following command to get the mouse and keyboard working:
sudo chmod 666 /dev/input/event*
# You need to open the live dashboard first.  
  
falkon "https://www.youtube.com/live_dashboard"  
  
### Stream to YouTube only tty.  
ffmpeg -f alsa -i pipewire -thread_queue_size 1024 -f fbdev -framerate 60 -i /dev/fb0 -c:v libx264 -preset ultrafast -tune zerolatency -pix_fmt yuv420p -c:a aac -b:a 128k -f flv -async 1 -ar 48000 -latency 100 -bufsize 1000k rtmp://a.rtmp.youtube.com/live2/KEY 2> /dev/null  
  
#### Stream to YouTube TTY with camera.  
ffmpeg -f alsa -i pipewire -thread_queue_size 1024 -f fbdev -framerate 60 -i /dev/fb0 -f v4l2 -framerate 60 -video_size 320x240 -i /dev/video0 -filter_complex "[2:v]scale=320:240[cam];[1:v][cam]overlay=main_w-overlay_w-10:main_h-overlay_h-10[outv]" -map "[outv]" -map 0:a -c:v libx264 -preset ultrafast -tune zerolatency -pix_fmt yuv420p -c:a aac -b:a 128k -f flv -bufsize 1000k rtmp://a.rtmp.youtube.com/live2/KEY 2> /dev/null  
  
### Stream to YouTube full cam.  
ffmpeg -f alsa -i pipewire -thread_queue_size 1024 -f v4l2 -framerate 60 -video_size 1280x720 -i /dev/video0 -c:v libx264 -preset ultrafast -tune zerolatency -pix_fmt yuv420p -c:a aac -b:a 128k -f flv -bufsize 1000k rtmp://a.rtmp.youtube.com/live2/KEY 2> /dev/null  
  
### Record video.  
ffmpeg -f alsa -i pipewire -f fbdev -r 30 -i /dev/fb0 record.mp4  
  

5. Additional Tips and Useful Tools

Mi archivo: .config/fish/config.fish


if status is-interactive
    # Commands to run in interactive sessions can go here
end

#if status --is-login
#    if test -z "$DISPLAY" -a $XDG_VTNR = 2
#        exec tmux
#    end
#end

if test -z "$TMUX" -a $XDG_VTNR = 1
  tmux attach || exec tmux new-session
end
if test -z "$TMUX" -a $XDG_VTNR = 5
  sudo pacman --noconfirm -Syu
end
if test -z "$TMUX" -a $XDG_VTNR = 2
  irssi
end
if test -z "$TMUX" -a $XDG_VTNR = 6
  mbsync -a
  neomutt
end

#sudo loadkeys /home/esotericwarfare/mi_mapa.kmap

set -xg WWW_BROWSER w3m
set BROWSER w3m
set -U fish_greeting
export BROWSER=w3m


#export QT_QPA_PLATFORM=wayland
#alias dgg 'w3m -sixel dgg.gg'
#alias f1 'bash scripts/f1exposure.sh'
#alias wgoogle 'cha -V google.com'
#alias wgoogle 'w3m -sixel google.com'
#alias tdgg 'w3m -sixel dgg.gg'
#alias imlauera 'w3m -sixel imlauera.github.io'
#alias cimlauera 'cha -V imlauera.github.io'
#alias invidious 'w3m -sixel https://inv.nadeko.net/feed/subscriptions'
#alias cinvidious 'cha -V https://inv.nadeko.net/feed/subscriptions'
#alias upwork="falkon upwork.com"
#alias linkedin="falkon linkedin.com"
#alias freelancer="falkon freelancer.com"
#alias duolingo="falkon https://duolingo.com/learn"
#alias f1="echo 'Los tiempos están en UTC. Coordinated Universal Time está 3 horas adelantado a Buenos Aires'; bash $HOME/scripts/f1exposure.sh | jq ."
#alias telegram="falkon web.telegram.org"

alias doom="cd doom; bash play_doom.sh;"
alias wiby="w3m http://wiby.org"
alias geohot="netsurf-fb -f sdl -w 1366 -h 768 https://geohot.github.io/blog"
alias ce="netsurf-fb -f sdl -w 1366 -h 768 http://cursoelectricidad.github.io"
alias el="netsurf-fb -f sdl -w 1366 -h 768 http://cursoelectrodomesticos.github.io"
alias mc="w3m https://sotwe.com/marianocrosetti"
alias in="netsurf-fb -f sdl -w 1366 -h 768 https://imlauernews.github.io"
alias im="netsurf-fb -f sdl -w 1366 -h 768 https://imlauer.github.io"
alias imlauer="netsurf-fb -f sdl -w 1366 -h 768 http://imlauera.github.io"
alias hp="netsurf-fb -f sdl -w 1366 -h 768 http://hyperphysics.phy-astr.gsu.edu/hbasees/hframe.html"
#alias news="netsurf-fb -f sdl -w 1366 -h 768 news.ycombinator.com"
alias news="lynx news.ycombinator.com"

alias ls='ls --color=auto'
alias grep='grep --color=auto'
alias ..="cd .."
#export QT_QPA_PLATFORM=wayland
export QT_QPA_PLATFORM=eglfs
#export QT_QPA_PLATFORM=linuxfb
#export QTWEBENGINE_CHROMIUM_FLAGS="--ignore-gpu-blacklist --disable-gpu"
export QTWEBENGINE_CHROMIUM_FLAGS="--ignore-gpu-blacklist"


export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
#export QT_QPA_FONTDIR=/lib/Fonts
#export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib/plugins/platforms
#export QT_QPA_EGLFS_PHYSICAL_WIDTH=155
#export QT_QPA_EGLFS_PHYSICAL_HEIGHT=86
#export QT_QPA_EGLFS_WIDTH=1024
#export QT_QPA_EGLFS_HEIGHT=614
#export QT_QPA_EGLFS_NO_LIBINPUT=0

#export QT_QPA_EGLFS_KEYBOARD_LAYOUT='es'
#export QT_QPA_EGLFS_KBD_MAP='es'

export QT_QPA_EGLFS_FULLSCREEN=1

export XKB_DEFAULT_LAYOUT=es
export XKB_DEFAULT_VARIANT=nodeadkeys

alias drudgereport="w3m drudgereport.com"
alias dgg='w3m  dgg.gg'
#alias google='cha -V google.com'
alias mojeek "w3m https://www.mojeek.com/search?q=hola"
alias google "w3m https://leta.mullvad.net/search?q=google&engine=google"
alias images2 "w3m https://www.ecosia.org/images?q=ecosia"
alias ecosia "w3m https://www.ecosia.org/search?q=ecosia"
alias blog='w3m imlauera.blogspot.com'
alias blog='w3m imlauer.blogspot.com'
alias tdgg='w3m  dgg.gg'
alias imlauera='cha -V imlauera.github.io'
alias analisismatematico2='netsurf-fb -f sdl -w 1366 -h 768 analisismatematico2.github.io'
alias wimlauera='w3m imlauera.github.io'
alias invidious='w3m  https://inv.nadeko.net/feed/subscriptions'
alias cinvidious='cha -V https://inv.nadeko.net/feed/subscriptions'
alias upwork="falkon upwork.com"
alias linkedin="falkon linkedin.com"
alias home="w3m $HOME/samba/offline_tastyfish/startpage.html"
alias freelancer="falkon freelancer.com"
alias duolingo="falkon https://duolingo.com/learn"
alias f1="bash $HOME/scripts/f1exposure.sh"
alias notebooklm="falkon https://notebooklm.google.com"
alias telegram="falkon web.telegram.org"
alias images="w3m https://pinterest.lurkmore.com/"
alias lyrics="w3m https://genius.lurkmore.com/"
alias rightdao="w3m https://rightdao.com"
alias ttt="torsocks w3m ~/projects/imlauer.github.io/index.html"
alias focus="sudo systemctl stop NetworkManager"



fish_add_path $HOME/.local/bin
set -gx ANDROID_HOME ~/Android/Sdk
set -gx PATH $PATH $ANDROID_HOME/cmdline-tools/bin $ANDROID_HOME/platform-tools

I read my news with newsboat and newsraft.

cat ~/.newsboat/urls

https://nobloatnews.github.io/rss.xml
https://cursoelectricidad.github.io/feed.xml
https://stallman.org/rss/rss.xml
https://geohot.github.io/blog/feed.xml
https://xcancel.com/sstricklandmma/rss
https://www.youtube.com/feeds/videos.xml?channel_id=UC3ts8coMP645hZw9JSD3pqQ
https://www.youtube.com/feeds/videos.xml?channel_id=UCld68syR8Wi-GY_n4CaoJGA
https://www.youtube.com/feeds/videos.xml?channel_id=UCbpe1SYzZKG4RswEnxxSRZQ
https://www.youtube.com/feeds/videos.xml?channel_id=UCdlKPiNQ_Dw20N9CzGms-XA
https://www.youtube.com/feeds/videos.xml?channel_id=UCwgKmJM4ZJQRJ-U5NjvR2dg
https://www.youtube.com/feeds/videos.xml?channel_id=UCxrN_J1dBX4ir-3xF8u3fUQ
https://www.youtube.com/feeds/videos.xml?channel_id=UCR4W7Mq0HD8JoW9KBRm0mZg
https://www.youtube.com/feeds/videos.xml?channel_id=UC1qH20lfqK4b_BgNQ-iP9Ww
https://www.youtube.com/feeds/videos.xml?channel_id=UCnhDCF3Slf9MlmYGIr47y-g
https://www.youtube.com/feeds/videos.xml?channel_id=UCZbjyqToF-4qmGNwYrhqQtQ
https://www.youtube.com/feeds/videos.xml?channel_id=UC2eYFnH61tmytImy1mTYvhA
https://www.youtube.com/feeds/videos.xml?channel_id=UCq-PF3nIPg5KO8po0dHcXsQ
https://www.youtube.com/feeds/videos.xml?channel_id=UC7YOGHUfC1Tb6E4pudI9STA
https://www.youtube.com/feeds/videos.xml?channel_id=UCDeWwrp2LUWkDSymrmnfKDQ
https://www.youtube.com/feeds/videos.xml?channel_id=UCylGUf9BvQooEFjgdNudoQg
https://www.youtube.com/feeds/videos.xml?channel_id=UCRfo-DAifrP3lzcxUHtGm_A
https://www.youtube.com/feeds/videos.xml?channel_id=UCrqM0Ym_NbK1fqeQG2VIohg