On 06.03.2025 15:46, Jan Stary wrote:
Hi,

On Mar 06 10:48:06, em...@kollof.nl wrote:
I was wondering if people with USB audio interfaces have the same issue
as me. When using the microphone of my usb audio interface, the recorded
audio starts to stutter/pop, indicating buffering problems, usually when
I do something that causes a bit of load on the system (e.g. starting a
browser). A good example of this happening is here:
https://youtu.be/Vbi5f1SlXZw?si=5pjaMI4aAf6Luewx&t=380 (at the 6:20
mark, the link should take you there)

I don't have this problem with any of my USB audio inerfaces.
How exactly are you recording this audio/video?
Can you replicate the problem with plain aucat -o?

(Still trying to reliably reproduce this. This seems to happen almost
reliably when I'm *not* actively monitoring things. It's almost
Heisenberg-like)

I'll attach the recording script I made for doing desktop recording and
streaming to this mail. You can flame my hacky ksh scripting :)
I would suspect the recording software rather than
tha audio subsystem itself, and it buffers etc.

At any rate, try to do the same with sndiod -ddd
running in a script(1) and show the results:
any xruns will be reported there.

Got that running in a seperate tag in dwm all the time for now. I do see
a lot of these:
chrome1: xrun, pause cycle
chrome0: xrun, pause cycle
rsnd/0: rec hw xrun, rused = 480 / 3840
rsnd/0: play hw xrun, pused = 3360 / 3840

It would be nice if sndiod debug could have timestamps so I can see
*when* things happen so I can correlate it a bit better with what I was
doing.

This also happens while videoconferencing with platforms like Teams and
Jitsi meet. The remote end claims I sound like a 'robot'.

Again, there are layers betwenn sndiod and what Teams and Jitsi
are doing (inside a browser I suppose? Which browser? Every browser?).

I think I solved the "robot" issue. It was artifacting that seems to
sporadicly happen when you plug your USB2 high speed audio interface in
a USB3 super speed port. I hear this is a common issue?

Cheers,
Emiel Kollof


#!/bin/ksh

# Help message
usage() {
    echo "Usage: $0 [-s screen] [-l] [-h] [-c config]"
    echo "  -s screen   Select screen number (0, 1, 2, etc.)"
    echo "  -l         List available screens"
    echo "  -h         Show this help message"
    echo "  -c config  Source configuration file for streaming"
    exit 1
}

# Function to list screens with xrandr
list_screens() {
    echo "Available screens:"
    xrandr --listactivemonitors | tail -n +2 | nl -v 0
}

# Function to get screen geometry for a given screen number
get_screen_geometry() {
    screen_num=$1
    echo "Debug: Looking for screen $screen_num"
    
    # Get the selected monitor line
    monitor_info=$(xrandr --listactivemonitors | tail -n +2 | sed -n 
"$((screen_num + 1))p")
    echo "Debug: Monitor info: $monitor_info"
    
    if [ -z "$monitor_info" ]; then
        echo "Error: Screen $screen_num not found" >&2
        exit 1
    fi

    # Get raw dimensions from xrandr --listmonitors (which shows actual pixels)
    raw_info=$(xrandr | grep -A1 "^Screen" | tail -n1)
    echo "Debug: Raw screen info: $raw_info"

    # First try to get current resolution from xrandr output
    current_mode=$(xrandr | grep -A1 "^$(echo "$monitor_info" | awk '{print 
$3}')" | grep -v "^--" | grep "*" | awk '{print $1}')
    echo "Debug: Current mode: $current_mode"

    if [ -n "$current_mode" ]; then
        SCREEN_WIDTH=$(echo "$current_mode" | cut -d'x' -f1)
        SCREEN_HEIGHT=$(echo "$current_mode" | cut -d'x' -f2)
    else
        # Fallback to parsing from monitor_info
        SCREEN_WIDTH=$(echo "$monitor_info" | awk '{print $3}' | cut -d'/' -f1)
        SCREEN_HEIGHT=$(echo "$monitor_info" | awk '{print $3}' | cut -d'x' -f2 
| cut -d'/' -f1)
    fi

    # Extract offsets
    SCREEN_OFFSET_X=$(echo "$monitor_info" | awk '{print $3}' | sed 
's/.*+\([0-9]*\)+.*/\1/')
    SCREEN_OFFSET_Y=$(echo "$monitor_info" | awk '{print $3}' | sed 
's/.*+[0-9]*+\([0-9]*\)/\1/')

    echo "Debug: Parsed values:"
    echo "Width: $SCREEN_WIDTH"
    echo "Height: $SCREEN_HEIGHT"
    echo "Offset X: $SCREEN_OFFSET_X"
    echo "Offset Y: $SCREEN_OFFSET_Y"

    # Verify we got valid numbers
    if [ -z "$SCREEN_WIDTH" ] || [ -z "$SCREEN_HEIGHT" ] || \
       [ -z "$SCREEN_OFFSET_X" ] || [ -z "$SCREEN_OFFSET_Y" ]; then
        echo "Error: Failed to parse screen dimensions" >&2
        exit 1
    fi
}

# Function to source config file
source_config() {
    config_file=$1
    if [ -f "$config_file" ]; then
        . "$config_file"
    else
        echo "Error: Config file $config_file not found" >&2
        exit 1
    fi
}

# Initialize variables
SCREEN=""
SCREEN_WIDTH=""
SCREEN_HEIGHT=""
SCREEN_OFFSET_X=""
SCREEN_OFFSET_Y=""
RTMP_URI=""
STREAM_KEY=""

# Parse command line options
while getopts "s:lhc:" opt; do
    case $opt in
        s)
            SCREEN=${OPTARG}
            get_screen_geometry "$SCREEN"
            ;;
        l)
            list_screens
            exit 0
            ;;
        h)
            usage
            ;;
        c)
            source_config "${OPTARG}"
            ;;
        *)
            echo "Invalid option: -$OPTARG" >&2
            usage
            ;;
    esac
done

# If no screen specified or geometry not set, show usage
if [ -z "$SCREEN" ] || [ -z "$SCREEN_WIDTH" ]; then
    echo "Error: No screen selected or screen geometry not found" >&2
    usage
fi

# Get current timestamp
NAME=$(date '+%Y-%m-%d_%H%M%S')

echo "Recording screen $SCREEN (${SCREEN_WIDTH}x${SCREEN_HEIGHT} at offset 
${SCREEN_OFFSET_X},${SCREEN_OFFSET_Y})"

# Determine output destination
if [ -n "$RTMP_URI" ] && [ -n "$STREAM_KEY" ]; then
    OUTPUT="$RTMP_URI/$STREAM_KEY.flv"
    echo "STREAMING"
else
    OUTPUT="$HOME/Videos/$NAME.mkv"
fi

ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 \
    -f sndio -thread_queue_size 4096 -i snd/0.mon \
    -f sndio -thread_queue_size 8192 -i snd/0 \
    -f x11grab -thread_queue_size 128 -probesize 32M -draw_mouse 1 \
    -video_size ${SCREEN_WIDTH}x${SCREEN_HEIGHT} -r 60 \
    -i :0.0+${SCREEN_OFFSET_X},${SCREEN_OFFSET_Y} \
    -filter_complex "\
        [0:a]volume=4.0,pan=stereo|c0=c0|c1=c1[desktop];\
        
[1:a]volume=3.0,acompressor=threshold=0.125:ratio=4:attack=200:release=1000,dynaudnorm=f=10:g=3:p=0.9,pan=stereo|c0=c0|c1=c1[mic];\
        [desktop][mic]amix=inputs=2:duration=first[aout]" \
    -map 2:v \
    -map '[aout]' \
    -c:v h264_vaapi \
    -vf 'format=nv12|vaapi,hwupload' \
    -qp 0 \
    -c:a aac \
    -b:a 160k \
    -ar 48000 \
    -preset ultrafast \
    -ac 2 \
    -crf 23 \
    -b:v 6500k \
    -fps_mode cfr \
    -async 1 \
    -vsync 1 \
    -flags +low_delay \
    -fflags +nobuffer \
    -use_wallclock_as_timestamps 1 \
    -y \
    "$OUTPUT"

if [ -z $RMTP_URI ]; then
  echo "Recording saved in $OUTPUT"
fi

Reply via email to