Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Friday, February 21, 2025

How to Set Up Kodi 21 with YouTube Add-on and HDMI-CEC on Raspberry Pi 5

This guide covers how to set up Kodi 21 (Omega) with the unofficial YouTube Add-on, Chorus2 web interface, and intelligent HDMI-CEC control on a Raspberry Pi 5 running Raspberry Pi OS (Debian 12/13).

1. Installing Kodi 21

Raspberry Pi repositories provide both kodi (v20) and kodi21 (v21 Omega). Install Kodi 21 along with the adaptive streaming library to prevent playback stuttering:

sudo apt-get update
sudo apt-get install kodi21 kodi21-inputstream-adaptive -y

2. Installing the Unofficial YouTube Plugin

cd ~/Downloads
wget https://ftp.fau.de/osmc/osmc/download/dev/anxdpanic/repositories/repository.yt.testing_unofficial-2.0.7.zip
  1. In Kodi: Settings → Add-ons → Install from zip file → Home folder → Downloads → repository.yt.testing_unofficial-2.0.7.zip.
  2. Under Add-ons, open the context menu / options at bottom left and select Check for updates.
  3. Select Install from repository → YouTube Test Repo (Unofficial) → Video add-ons → YouTube → Install.

3. YouTube Personal API v3 Keys

To avoid hitting shared API quota limits, generate personal Google Cloud credentials (Setup Guide):

  • Create a project in Google Cloud Console with YouTube Data API v3 enabled.
  • Create an OAuth 2.0 Client ID (Application type: TV and Limited Input devices) and an API Key. Ensure the Publishing Status in OAuth Consent Screen is set to Production.
  • In Kodi: YouTube → Settings → API and enter your API Key, Client ID, and Client Secret.

4. Installing the Chorus2 Web Interface

Install the latest Chorus2 web control interface:

tmp="$(mktemp -d)"
curl -L -o "$tmp/chorus2.zip" https://github.com/xbmc/chorus2/archive/refs/heads/master.zip
unzip -q "$tmp/chorus2.zip" -d "$tmp"

mkdir -p ~/.kodi/addons
rm -rf ~/.kodi/addons/webinterface.default.new
cp -a "$tmp"/chorus2-master/dist ~/.kodi/addons/webinterface.default.new

if [ -d ~/.kodi/addons/webinterface.default ]; then
  mv ~/.kodi/addons/webinterface.default ~/.kodi/addons/webinterface.default.bak.$(date +%Y%m%d-%H%M%S)
fi

mv ~/.kodi/addons/webinterface.default.new ~/.kodi/addons/webinterface.default
rm -rf "$tmp"

5. Fine-Tuning HDMI-CEC Power Behavior

To prevent your Raspberry Pi from turning on your TV every time it reboots, add this parameter to /boot/firmware/config.txt:

hdmi_ignore_cec_init=1

Configure automatic playback pausing in Kodi when you switch TV inputs or turn off the screen:

  • Navigate to: Kodi → Settings → System → Input → Peripherals → CEC Adapter
  • Set Action when switching to another source → Stop playback
  • Set When the TV is switched off → Stop playback

6. Wayland Autostart / Remote Launch Script (/scripts/youtube.py)

To launch Kodi remotely over SSH, DBus, or a Telegram bot under Wayland without display collisions:

#!/usr/bin/env python3
import os

os.chdir('/home/pi')
os.environ["DISPLAY"] = ":0"
os.environ["WAYLAND_DISPLAY"] = "wayland-0"
os.environ["XDG_RUNTIME_DIR"] = "/run/user/1000"
os.environ["DBUS_SESSION_BUS_ADDRESS"] = "unix:path=/run/user/1000/bus"

# Terminate competing browser windows before launching media center
os.system("pkill -9 -f 'chrome|chromium|google-chrome|kodi|kodi21.bin'")
os.system('/usr/bin/kodi &')

Saturday, February 10, 2024

How to Capture Screenshots over SSH on Debian 12 Wayland Desktops

On legacy Debian 11 (Bullseye) and older X11 desktops, taking a screenshot of an active desktop session remotely over SSH was straightforward using scrot:

DISPLAY=:0.0 scrot -o screenshot.jpg

In Python:

import os
os.environ["DISPLAY"] = ":0.0"
os.system("scrot -o screenshot.jpg")

Wayland on Debian 12 (Bookworm)

On Debian 12 (and Raspberry Pi OS Bookworm with Wayfire or labwc), Wayland is the default compositor. Because Wayland enforces strict security isolation between graphical clients and display sockets, scrot will fail with the error:

failed to create display

To take screenshots under Wayland, use the native grim utility (pre-installed on Raspberry Pi OS). When calling grim over SSH from a non-interactive TTY, you must explicitly export both WAYLAND_DISPLAY and XDG_RUNTIME_DIR:

WAYLAND_DISPLAY=wayland-1 XDG_RUNTIME_DIR=/run/user/1000 grim screenshot.png

Python Automation Script

To capture screenshots programmatically in Python over SSH:

import os

pngfile = "/tmp/screenshot.png"
os.environ["WAYLAND_DISPLAY"] = "wayland-1"
os.environ["XDG_RUNTIME_DIR"] = "/run/user/1000"

os.system(f"grim {pngfile}")
Tip: If you are unsure of your socket names, run echo $WAYLAND_DISPLAY and echo $XDG_RUNTIME_DIR from a terminal inside the active desktop session, or check the socket files in /run/user/$(id -u)/.

Wednesday, July 5, 2023

How to Configure Eturnal TURN Server with TLS 1.3 and Static Credentials on Debian 12

Eturnal is a modern, lightweight STUN/TURN server written in Erlang that serves as an efficient alternative to Coturn with built-in TLS 1.3 support. While Eturnal natively uses time-limited ephemeral credentials (REST API authentication), many WebRTC clients require static usernames and passwords. Here is how to configure Eturnal on Debian 12 and generate static credentials using an HMAC-SHA1 Python helper.

Stack: Eturnal 1.12+ • Debian 12 Bookworm • TLS 1.3 • HMAC-SHA1 Password Generator

1. Installing Eturnal on Debian 12

# Add Eturnal package repository and install
curl -fsSL https://eturnal.net/gpg.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/eturnal.gpg
echo "deb https://eturnal.net/debian bookworm main" | sudo tee /etc/apt/sources.list.d/eturnal.list
sudo apt-get update && sudo apt-get install eturnal -y

2. Generating Static TURN Credentials via Python

To produce valid credentials matching your configured shared secret (secret: "YOUR_SHARED_SECRET" in /etc/eturnal.yml):

import time
import hmac
import hashlib
import base64

SHARED_SECRET = "YOUR_SHARED_SECRET"
# Set expiration timestamp (e.g. 1 year in the future)
expiry = int(time.time()) + (365 * 24 * 3600)
username = f"{expiry}:user1"

# Compute HMAC-SHA1 hash
key = SHARED_SECRET.encode('utf-8')
msg = username.encode('utf-8')
password = base64.b64encode(hmac.new(key, msg, hashlib.sha1).digest()).decode('utf-8')

print(f"TURN Username: {username}")
print(f"TURN Password: {password}")

Sunday, April 23, 2023

How to Suppress OpenCV and GStreamer nvarguscamerasrc (GST_ARGUS) Debug Logs on NVIDIA Jetson

When capturing MIPI CSI camera video on NVIDIA Jetson Nano, Xavier, or Orin platforms using OpenCV with GStreamer's nvarguscamerasrc plugin, the driver constantly spams stdout and stderr with verbose hardcoded debug strings (such as GST_ARGUS: Creating output stream and CONSUMER: Waiting until producer is connected...).

Why Log Levels Don't Work: These prints are hardcoded inside NVIDIA's gstnvarguscamerasrc.cpp C++ source code via printf(), bypassing standard GStreamer debug level filters (GST_DEBUG=0).

1. Rebuilding nvarguscamerasrc Without Hardcoded Prints

Download your matching JetPack BSP public sources and remove the hardcoded print macros:

# Check active L4T release
cat /etc/nv_tegra_release

# Extract gst-nvarguscamera source
cd ~/src/Linux_for_Tegra/source/public
tar -jxvf gst-nvarguscamera_src.tbz2
cd gst-nvarguscamera/

# Edit gstnvarguscamerasrc.cpp and empty out the print macros:
sed -i 's/#define GST_ARGUS_PRINT(...) printf(__VA_ARGS__)/#define GST_ARGUS_PRINT(...)/g' gstnvarguscamerasrc.cpp
sed -i 's/#define CONSUMER_PRINT(...) printf(__VA_ARGS__)/#define CONSUMER_PRINT(...)/g' gstnvarguscamerasrc.cpp

# Compile and install plugin
make
sudo make install

2. Suppressing OpenCV Warnings in Python

In your Python application, silence OpenCV library logs and restart the camera daemon prior to acquisition:

import os
import warnings

# Suppress Python warnings & OpenCV internal logging
warnings.filterwarnings('ignore')
os.environ["OPENCV_LOG_LEVEL"] = "OFF"

# Restart camera daemon to ensure clean hardware state
os.system("sudo systemctl restart nvargus-daemon")

Your camera capture scripts will now run silently without terminal clutter.

Friday, March 17, 2017

How to Build a Dynamic PowerDNS Pipe Backend in Python

The PowerDNS Pipe Backend allows developers to attach custom external scripts (written in Python, Perl, Bash, or Go) to resolve DNS queries dynamically over standard I/O streams. This approach is ideal for dynamically serving CNAME aliases, geo-routing records, or integrating DNS responses with external APIs without rebuilding PowerDNS.

Environment: PowerDNS 3.x / 4.x • pdns-backend-pipe • Python IPC

1. Installing PowerDNS Pipe Backend (CentOS / RHEL)

yum install pdns pdns-backend-pipe -y

Configure /etc/pdns/pdns.conf to launch the pipe backend alongside standard zone providers:

launch=bind,pipe
pipe-command=/etc/pdns/pdns-backend.py

2. The Python Backend Script (/etc/pdns/pdns-backend.py)

The script communicates with PowerDNS via tab-delimited protocol over stdin/stdout. Note the -u flag on Python to ensure unbuffered I/O:

#!/usr/bin/python -u
from sys import stdin, stdout

# Handshake initialization
data = stdin.readline()
stdout.write("OK	My Dynamic Python Backend
")
stdout.flush()

TARGET_CNAME = 'cname-target.example.com'

while True:
    line = stdin.readline()
    if not line:
        break
    data = line.strip()
    kind, qname, qclass, qtype, qid, ip = data.split('	')
    
    if kind == 'Q' and qname not in TARGET_CNAME:
        # Provide SOA record for authoritative delegation
        soa_resp = f"DATA	{qname}	{qclass}	SOA	86400	-1	support.{qname} ns1.example.org 2026010100 1800 3600 604800 3600
"
        stdout.write(soa_resp)
        
        # Respond to ANY or CNAME queries
        if qtype in ('ANY', 'CNAME'):
            cname_resp = f"DATA	{qname}	{qclass}	CNAME	86400	{qid}	{TARGET_CNAME}
"
            stdout.write(cname_resp)
            
    stdout.write("END
")
    stdout.flush()

Make the script executable and restart PowerDNS:

chmod +x /etc/pdns/pdns-backend.py
systemctl restart pdns

Tuesday, November 22, 2016

How to Install Taiga Open Source Agile Project Manager & Kanban on CentOS 7

Taiga is a beautiful, open-source project management platform tailored for agile teams, Scrum sprints, and Kanban workflows. While official documentation primarily targeted Ubuntu, Taiga deploys smoothly on CentOS 7 with PostgreSQL, Python virtualenvs, and Nginx.

Architecture: taiga-back (Django / Python 3.5+) • taiga-front (AngularJS HTML5) • PostgreSQL 9.4+ • Nginx reverse proxy

1. Installing System Packages on CentOS 7

Install prerequisite development libraries and PostgreSQL:

yum install epel-release -y
yum install gcc gcc-c++ make automake git zlib-devel bzip2-devel openssl-devel   ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel   libpcap-devel xz-devel libjpeg-turbo-devel libxml2-devel libxslt-devel   postgresql-server postgresql-devel redis nginx -y

2. PostgreSQL Setup

postgresql-setup initdb
systemctl start postgresql
systemctl enable postgresql

sudo -u postgres createuser -s taiga
sudo -u postgres createdb -O taiga taiga

3. Frontend & Backend Deployment

Deploy taiga-back inside an isolated Python virtual environment, execute database migrations via python manage.py migrate, unpack taiga-front-dist to /home/taiga/taiga-front-dist, and configure Nginx to proxy API endpoints to Gunicorn on port 8001.

Tuesday, September 13, 2016

Setting Up Vim with Python 2/3 Support and Code Completion on Ubuntu 16.04

Configuring Vim as a fast, keyboard-driven Python IDE significantly boosts developer productivity. When following standard Vim Python configuration guides on Ubuntu 16.04 (Xenial Xerus), several key adjustments are required to achieve clean PEP 8 indentation, accurate syntax highlighting, and YouCompleteMe code autocompletion.

Stack: Ubuntu 16.04 LTS • Vim 7.4 / 8.0 • Python PEP 8 indentation rules

1. Enforcing Clean PEP 8 Indentation

Add the following configuration to your ~/.vimrc to ensure 4-space indentations, soft tabs, and trailing whitespace highlighting:

" PEP 8 standard formatting for Python buffers
augroup python_indent
    autocmd!
    autocmd FileType python setlocal tabstop=4
    autocmd FileType python setlocal softtabstop=4
    autocmd FileType python setlocal shiftwidth=4
    autocmd FileType python setlocal textwidth=79
    autocmd FileType python setlocal expandtab
    autocmd FileType python setlocal autoindent
    autocmd FileType python setlocal fileformat=unix
augroup END

2. Installing YouCompleteMe on Ubuntu 16.04

Install prerequisite development libraries before compiling the YCM C-extension:

sudo apt-get install build-essential cmake python-dev python3-dev -y
cd ~/.vim/bundle/YouCompleteMe
./install.py --clang-completer

How Google Antigravity Solved the Mysterious NVIDIA Sleep Reboot on My Dell Inspiron 7567 (Ubuntu Linux)

If you run modern Ubuntu or Linux on a Dell Inspiron 15 Gaming (7567) or a similar 7th-gen Intel laptop paired with an NVIDIA GeForce GTX ...