fix(sync): harden mjpeg uvc capture path
This commit is contained in:
parent
8b5dc220ad
commit
ecc5b6df87
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1642,7 +1642,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.14.30"
|
version = "0.14.31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@ -1676,7 +1676,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.14.30"
|
version = "0.14.31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
@ -1688,7 +1688,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.14.30"
|
version = "0.14.31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|||||||
@ -4,7 +4,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.14.30"
|
version = "0.14.31"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.14.30"
|
version = "0.14.31"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ render_uvc_env_file() {
|
|||||||
# generated by lesavka/scripts/install/server.sh
|
# generated by lesavka/scripts/install/server.sh
|
||||||
# Edit only for local UVC hardware overrides; rerunning the installer refreshes defaults.
|
# Edit only for local UVC hardware overrides; rerunning the installer refreshes defaults.
|
||||||
LESAVKA_UVC_DEBUG=${LESAVKA_UVC_DEBUG:-1}
|
LESAVKA_UVC_DEBUG=${LESAVKA_UVC_DEBUG:-1}
|
||||||
LESAVKA_UVC_MAXPACKET=${LESAVKA_UVC_MAXPACKET:-256}
|
LESAVKA_UVC_MAXPACKET=${LESAVKA_UVC_MAXPACKET:-1024}
|
||||||
LESAVKA_UVC_LIMIT_PCT=${LESAVKA_UVC_LIMIT_PCT:-100}
|
LESAVKA_UVC_LIMIT_PCT=${LESAVKA_UVC_LIMIT_PCT:-100}
|
||||||
LESAVKA_UVC_FPS=${LESAVKA_UVC_FPS:-20}
|
LESAVKA_UVC_FPS=${LESAVKA_UVC_FPS:-20}
|
||||||
LESAVKA_UVC_INTERVAL=${LESAVKA_UVC_INTERVAL:-500000}
|
LESAVKA_UVC_INTERVAL=${LESAVKA_UVC_INTERVAL:-500000}
|
||||||
|
|||||||
@ -19,8 +19,9 @@ TAIL_SECONDS=${TAIL_SECONDS:-2}
|
|||||||
CAPTURE_SECONDS=${CAPTURE_SECONDS:-$((PROBE_DURATION_SECONDS + PROBE_WARMUP_SECONDS + LEAD_IN_SECONDS + TAIL_SECONDS))}
|
CAPTURE_SECONDS=${CAPTURE_SECONDS:-$((PROBE_DURATION_SECONDS + PROBE_WARMUP_SECONDS + LEAD_IN_SECONDS + TAIL_SECONDS))}
|
||||||
REMOTE_CAPTURE=${REMOTE_CAPTURE:-/tmp/lesavka-upstream-av-sync.mkv}
|
REMOTE_CAPTURE=${REMOTE_CAPTURE:-/tmp/lesavka-upstream-av-sync.mkv}
|
||||||
LOCAL_OUTPUT_DIR=${LOCAL_OUTPUT_DIR:-"${REPO_ROOT}/tmp"}
|
LOCAL_OUTPUT_DIR=${LOCAL_OUTPUT_DIR:-"${REPO_ROOT}/tmp"}
|
||||||
|
REMOTE_VIDEO_DEVICE=${REMOTE_VIDEO_DEVICE:-auto}
|
||||||
VIDEO_SIZE=${VIDEO_SIZE:-auto}
|
VIDEO_SIZE=${VIDEO_SIZE:-auto}
|
||||||
VIDEO_FPS=${VIDEO_FPS:-30}
|
VIDEO_FPS=${VIDEO_FPS:-auto}
|
||||||
VIDEO_FORMAT=${VIDEO_FORMAT:-mjpeg}
|
VIDEO_FORMAT=${VIDEO_FORMAT:-mjpeg}
|
||||||
REMOTE_CAPTURE_STACK=${REMOTE_CAPTURE_STACK:-pulse}
|
REMOTE_CAPTURE_STACK=${REMOTE_CAPTURE_STACK:-pulse}
|
||||||
REMOTE_PULSE_CAPTURE_TOOL=${REMOTE_PULSE_CAPTURE_TOOL:-ffmpeg}
|
REMOTE_PULSE_CAPTURE_TOOL=${REMOTE_PULSE_CAPTURE_TOOL:-ffmpeg}
|
||||||
@ -120,6 +121,7 @@ echo "==> starting Tethys capture on ${TETHYS_HOST}"
|
|||||||
ssh ${SSH_OPTS} "${TETHYS_HOST}" bash -s -- \
|
ssh ${SSH_OPTS} "${TETHYS_HOST}" bash -s -- \
|
||||||
"${REMOTE_CAPTURE}" \
|
"${REMOTE_CAPTURE}" \
|
||||||
"${CAPTURE_SECONDS}" \
|
"${CAPTURE_SECONDS}" \
|
||||||
|
"${REMOTE_VIDEO_DEVICE}" \
|
||||||
"${VIDEO_SIZE}" \
|
"${VIDEO_SIZE}" \
|
||||||
"${VIDEO_FPS}" \
|
"${VIDEO_FPS}" \
|
||||||
"${VIDEO_FORMAT}" \
|
"${VIDEO_FORMAT}" \
|
||||||
@ -133,14 +135,15 @@ ssh ${SSH_OPTS} "${TETHYS_HOST}" bash -s -- \
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
remote_capture=$1
|
remote_capture=$1
|
||||||
capture_seconds=$2
|
capture_seconds=$2
|
||||||
video_size=$3
|
remote_video_device=$3
|
||||||
video_fps=$4
|
video_size=$4
|
||||||
video_format=$5
|
video_fps=$5
|
||||||
remote_capture_stack=$6
|
video_format=$6
|
||||||
remote_pulse_capture_tool=$7
|
remote_capture_stack=$7
|
||||||
remote_pulse_video_mode=$8
|
remote_pulse_capture_tool=$8
|
||||||
remote_audio_source=$9
|
remote_pulse_video_mode=$9
|
||||||
remote_audio_quiesce_user_audio=${10}
|
remote_audio_source=${10}
|
||||||
|
remote_audio_quiesce_user_audio=${11}
|
||||||
|
|
||||||
rm -f "${remote_capture}"
|
rm -f "${remote_capture}"
|
||||||
|
|
||||||
@ -156,6 +159,44 @@ quiesce_user_audio() {
|
|||||||
sleep 1
|
sleep 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolve_video_device() {
|
||||||
|
local requested=$1
|
||||||
|
if [[ "${requested}" != "auto" ]]; then
|
||||||
|
printf '%s\n' "${requested}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local by_id
|
||||||
|
by_id=$(find /dev/v4l/by-id -maxdepth 1 -type l -name '*Lesavka*video-index0' 2>/dev/null | head -n1 || true)
|
||||||
|
if [[ -n "${by_id}" ]]; then
|
||||||
|
printf '%s\n' "${by_id}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v v4l2-ctl >/dev/null 2>&1; then
|
||||||
|
local resolved
|
||||||
|
resolved="$(
|
||||||
|
v4l2-ctl --list-devices 2>/dev/null \
|
||||||
|
| awk '
|
||||||
|
BEGIN { want=0 }
|
||||||
|
/Lesavka Composite: UVC Camera/ { want=1; next }
|
||||||
|
/^[^ \t]/ { want=0 }
|
||||||
|
want && /^[ \t]+\/dev\/video[0-9]+/ {
|
||||||
|
gsub(/^[ \t]+/, "", $0)
|
||||||
|
print
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
'
|
||||||
|
)"
|
||||||
|
if [[ -n "${resolved}" ]]; then
|
||||||
|
printf '%s\n' "${resolved}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '/dev/video0\n'
|
||||||
|
}
|
||||||
|
|
||||||
resolve_pulse_source() {
|
resolve_pulse_source() {
|
||||||
if ! command -v pactl >/dev/null 2>&1; then
|
if ! command -v pactl >/dev/null 2>&1; then
|
||||||
return 1
|
return 1
|
||||||
@ -178,13 +219,13 @@ gst_video_source_caps() {
|
|||||||
printf 'image/jpeg,width=%s,height=%s,framerate=%s/1' \
|
printf 'image/jpeg,width=%s,height=%s,framerate=%s/1' \
|
||||||
"${resolved_video_size%x*}" \
|
"${resolved_video_size%x*}" \
|
||||||
"${resolved_video_size#*x}" \
|
"${resolved_video_size#*x}" \
|
||||||
"${video_fps}"
|
"${resolved_video_fps}"
|
||||||
;;
|
;;
|
||||||
yuyv422|YUYV|yuyv)
|
yuyv422|YUYV|yuyv)
|
||||||
printf 'video/x-raw,format=YUY2,width=%s,height=%s,framerate=%s/1' \
|
printf 'video/x-raw,format=YUY2,width=%s,height=%s,framerate=%s/1' \
|
||||||
"${resolved_video_size%x*}" \
|
"${resolved_video_size%x*}" \
|
||||||
"${resolved_video_size#*x}" \
|
"${resolved_video_size#*x}" \
|
||||||
"${video_fps}"
|
"${resolved_video_fps}"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
printf 'unsupported gst video_format=%s\n' "${video_format}" >&2
|
printf 'unsupported gst video_format=%s\n' "${video_format}" >&2
|
||||||
@ -208,18 +249,56 @@ gst_video_decode_chain() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_video_profile() {
|
||||||
|
if ! command -v v4l2-ctl >/dev/null 2>&1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
v4l2-ctl -d "${resolved_video_device}" --all 2>/dev/null \
|
||||||
|
| awk '
|
||||||
|
/Width\/Height[[:space:]]*:/ {
|
||||||
|
split($0, a, ":")
|
||||||
|
gsub(/^[ \t]+/, "", a[2])
|
||||||
|
split(a[2], wh, "/")
|
||||||
|
width=wh[1]
|
||||||
|
height=wh[2]
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/Frames per second:/ {
|
||||||
|
fps=$4
|
||||||
|
sub(/\..*/, "", fps)
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (width != "" && height != "") {
|
||||||
|
print "size=" width "x" height
|
||||||
|
}
|
||||||
|
if (fps != "") {
|
||||||
|
print "fps=" fps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
resolve_video_size() {
|
resolve_video_size() {
|
||||||
local requested=$1
|
local requested=$1
|
||||||
if [[ "${requested}" != "auto" ]]; then
|
if [[ "${requested}" != "auto" ]]; then
|
||||||
printf '%s\n' "${requested}"
|
printf '%s\n' "${requested}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
local current_profile
|
||||||
|
current_profile="$(current_video_profile || true)"
|
||||||
|
local current_size
|
||||||
|
current_size="$(awk -F= '/^size=/{print $2; exit}' <<<"${current_profile}")"
|
||||||
|
if [[ -n "${current_size}" ]]; then
|
||||||
|
printf '%s\n' "${current_size}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
if ! command -v v4l2-ctl >/dev/null 2>&1; then
|
if ! command -v v4l2-ctl >/dev/null 2>&1; then
|
||||||
printf '1280x720\n'
|
printf '640x480\n'
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
local listing
|
local listing
|
||||||
listing="$(v4l2-ctl -d /dev/video0 --list-formats-ext 2>/dev/null || true)"
|
listing="$(v4l2-ctl -d "${resolved_video_device}" --list-formats-ext 2>/dev/null || true)"
|
||||||
local preferred
|
local preferred
|
||||||
for preferred in 1920x1080 1360x768 1280x720; do
|
for preferred in 1920x1080 1360x768 1280x720; do
|
||||||
if grep -q "Size: Discrete ${preferred}" <<<"${listing}"; then
|
if grep -q "Size: Discrete ${preferred}" <<<"${listing}"; then
|
||||||
@ -227,7 +306,42 @@ resolve_video_size() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
printf '1280x720\n'
|
local first_size
|
||||||
|
first_size="$(grep -m1 -o 'Size: Discrete [0-9]\+x[0-9]\+' <<<"${listing}" | awk '{print $3}' || true)"
|
||||||
|
if [[ -n "${first_size}" ]]; then
|
||||||
|
printf '%s\n' "${first_size}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
printf '640x480\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_video_fps() {
|
||||||
|
local requested=$1
|
||||||
|
if [[ "${requested}" != "auto" ]]; then
|
||||||
|
printf '%s\n' "${requested}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local current_profile
|
||||||
|
current_profile="$(current_video_profile || true)"
|
||||||
|
local current_fps
|
||||||
|
current_fps="$(awk -F= '/^fps=/{print $2; exit}' <<<"${current_profile}")"
|
||||||
|
if [[ -n "${current_fps}" ]]; then
|
||||||
|
printf '%s\n' "${current_fps}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if ! command -v v4l2-ctl >/dev/null 2>&1; then
|
||||||
|
printf '20\n'
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local listing
|
||||||
|
listing="$(v4l2-ctl -d "${resolved_video_device}" --list-formats-ext 2>/dev/null || true)"
|
||||||
|
local first_fps
|
||||||
|
first_fps="$(grep -m1 -o '[0-9]\+\.[0-9]\+ fps' <<<"${listing}" | awk '{sub(/\..*/, "", $1); print $1}' || true)"
|
||||||
|
if [[ -n "${first_fps}" ]]; then
|
||||||
|
printf '%s\n' "${first_fps}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
printf '20\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_pw_audio_target() {
|
resolve_pw_audio_target() {
|
||||||
@ -327,15 +441,31 @@ case "${remote_capture_stack}" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
resolved_video_device="$(resolve_video_device "${remote_video_device}")"
|
||||||
resolved_video_size="$(resolve_video_size "${video_size}")"
|
resolved_video_size="$(resolve_video_size "${video_size}")"
|
||||||
printf 'using video mode: %s (%s)\n' "${resolved_video_size}" "${video_format:-driver-default}" >&2
|
resolved_video_fps="$(resolve_video_fps "${video_fps}")"
|
||||||
video_args=(-f video4linux2 -framerate "${video_fps}" -video_size "${resolved_video_size}")
|
printf 'using video device: %s\n' "${resolved_video_device}" >&2
|
||||||
|
printf 'using video mode: %s @ %s fps (%s)\n' "${resolved_video_size}" "${resolved_video_fps}" "${video_format:-driver-default}" >&2
|
||||||
|
video_args=(-f video4linux2 -framerate "${resolved_video_fps}" -video_size "${resolved_video_size}")
|
||||||
if [[ -n "${video_format}" ]]; then
|
if [[ -n "${video_format}" ]]; then
|
||||||
video_args+=(-input_format "${video_format}")
|
video_args+=(-input_format "${video_format}")
|
||||||
fi
|
fi
|
||||||
gst_source_caps="$(gst_video_source_caps)"
|
gst_source_caps="$(gst_video_source_caps)"
|
||||||
gst_decode_chain="$(gst_video_decode_chain)"
|
gst_decode_chain="$(gst_video_decode_chain)"
|
||||||
|
|
||||||
|
run_ffmpeg_capture() {
|
||||||
|
local rc=0
|
||||||
|
timeout --signal=INT "$((capture_seconds + 5))" "$@" || rc=$?
|
||||||
|
case "${rc}" in
|
||||||
|
0|124|130)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return "${rc}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
quiesce_for_alsa=0
|
quiesce_for_alsa=0
|
||||||
case "${remote_audio_quiesce_user_audio}" in
|
case "${remote_audio_quiesce_user_audio}" in
|
||||||
1|true|yes)
|
1|true|yes)
|
||||||
@ -372,7 +502,7 @@ if [[ "${capture_mode}" == "pwpipe" ]]; then
|
|||||||
| pw-v4l2 ffmpeg -hide_banner -loglevel error -y \
|
| pw-v4l2 ffmpeg -hide_banner -loglevel error -y \
|
||||||
-thread_queue_size 1024 \
|
-thread_queue_size 1024 \
|
||||||
"${video_args[@]}" \
|
"${video_args[@]}" \
|
||||||
-i /dev/video0 \
|
-i "${resolved_video_device}" \
|
||||||
-thread_queue_size 1024 \
|
-thread_queue_size 1024 \
|
||||||
-f s16le -ar 48000 -ac 2 \
|
-f s16le -ar 48000 -ac 2 \
|
||||||
-i pipe:0 \
|
-i pipe:0 \
|
||||||
@ -386,10 +516,10 @@ elif [[ "${capture_mode}" == "pulse" ]]; then
|
|||||||
ffmpeg)
|
ffmpeg)
|
||||||
case "${remote_pulse_video_mode}" in
|
case "${remote_pulse_video_mode}" in
|
||||||
copy)
|
copy)
|
||||||
ffmpeg -hide_banner -loglevel error -y \
|
run_ffmpeg_capture ffmpeg -hide_banner -loglevel error -y \
|
||||||
-thread_queue_size 1024 \
|
-thread_queue_size 1024 \
|
||||||
"${video_args[@]}" \
|
"${video_args[@]}" \
|
||||||
-i /dev/video0 \
|
-i "${resolved_video_device}" \
|
||||||
-thread_queue_size 1024 \
|
-thread_queue_size 1024 \
|
||||||
-f pulse \
|
-f pulse \
|
||||||
-i "${pulse_source}" \
|
-i "${pulse_source}" \
|
||||||
@ -399,15 +529,15 @@ elif [[ "${capture_mode}" == "pulse" ]]; then
|
|||||||
"${remote_capture}"
|
"${remote_capture}"
|
||||||
;;
|
;;
|
||||||
cfr)
|
cfr)
|
||||||
ffmpeg -hide_banner -loglevel error -y \
|
run_ffmpeg_capture ffmpeg -hide_banner -loglevel error -y \
|
||||||
-thread_queue_size 1024 \
|
-thread_queue_size 1024 \
|
||||||
"${video_args[@]}" \
|
"${video_args[@]}" \
|
||||||
-i /dev/video0 \
|
-i "${resolved_video_device}" \
|
||||||
-thread_queue_size 1024 \
|
-thread_queue_size 1024 \
|
||||||
-f pulse \
|
-f pulse \
|
||||||
-i "${pulse_source}" \
|
-i "${pulse_source}" \
|
||||||
-t "${capture_seconds}" \
|
-t "${capture_seconds}" \
|
||||||
-vf "fps=${video_fps}" \
|
-vf "fps=${resolved_video_fps}" \
|
||||||
-c:v libx264 -preset ultrafast -crf 12 -g 1 -pix_fmt yuv420p \
|
-c:v libx264 -preset ultrafast -crf 12 -g 1 -pix_fmt yuv420p \
|
||||||
-c:a pcm_s16le \
|
-c:a pcm_s16le \
|
||||||
"${remote_capture}"
|
"${remote_capture}"
|
||||||
@ -428,7 +558,7 @@ elif [[ "${capture_mode}" == "pulse" ]]; then
|
|||||||
timeout --signal=INT "$((capture_seconds + 3))" \
|
timeout --signal=INT "$((capture_seconds + 3))" \
|
||||||
gst-launch-1.0 -q -e \
|
gst-launch-1.0 -q -e \
|
||||||
matroskamux name=mux ! filesink location="${remote_capture}" \
|
matroskamux name=mux ! filesink location="${remote_capture}" \
|
||||||
v4l2src device=/dev/video0 do-timestamp=true ! \
|
v4l2src device="${resolved_video_device}" do-timestamp=true ! \
|
||||||
${gst_source_caps} ! \
|
${gst_source_caps} ! \
|
||||||
queue ! mux. \
|
queue ! mux. \
|
||||||
pulsesrc device="${pulse_source}" do-timestamp=true ! \
|
pulsesrc device="${pulse_source}" do-timestamp=true ! \
|
||||||
@ -439,7 +569,7 @@ elif [[ "${capture_mode}" == "pulse" ]]; then
|
|||||||
timeout --signal=INT "$((capture_seconds + 3))" \
|
timeout --signal=INT "$((capture_seconds + 3))" \
|
||||||
gst-launch-1.0 -q -e \
|
gst-launch-1.0 -q -e \
|
||||||
matroskamux name=mux ! filesink location="${remote_capture}" \
|
matroskamux name=mux ! filesink location="${remote_capture}" \
|
||||||
v4l2src device=/dev/video0 do-timestamp=true ! \
|
v4l2src device="${resolved_video_device}" do-timestamp=true ! \
|
||||||
${gst_source_caps} ! \
|
${gst_source_caps} ! \
|
||||||
${gst_decode_chain} \
|
${gst_decode_chain} \
|
||||||
videoconvert ! videorate ! video/x-raw,framerate="${video_fps}"/1 ! \
|
videoconvert ! videorate ! video/x-raw,framerate="${video_fps}"/1 ! \
|
||||||
@ -462,10 +592,10 @@ elif [[ "${capture_mode}" == "pulse" ]]; then
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
ffmpeg -hide_banner -loglevel error -y \
|
run_ffmpeg_capture ffmpeg -hide_banner -loglevel error -y \
|
||||||
-thread_queue_size 1024 \
|
-thread_queue_size 1024 \
|
||||||
"${video_args[@]}" \
|
"${video_args[@]}" \
|
||||||
-i /dev/video0 \
|
-i "${resolved_video_device}" \
|
||||||
-thread_queue_size 1024 \
|
-thread_queue_size 1024 \
|
||||||
-f alsa -ac 2 -ar 48000 \
|
-f alsa -ac 2 -ar 48000 \
|
||||||
-i "${alsa_audio_dev}" \
|
-i "${alsa_audio_dev}" \
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bench = false
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.14.30"
|
version = "0.14.31"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
autobins = false
|
autobins = false
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UPSTREAM_PLAYOUT_DELAY_MS:-1000}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UPSTREAM_PLAYOUT_DELAY_MS:-1000}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UPSTREAM_PAIR_SLACK_US:-20000}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UPSTREAM_PAIR_SLACK_US:-20000}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UPSTREAM_STALE_DROP_MS:-80}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UPSTREAM_STALE_DROP_MS:-80}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_MAXPACKET:-256}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_MAXPACKET:-1024}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_INTERVAL:-500000}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_INTERVAL:-500000}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_WIDTH:-640}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_WIDTH:-640}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_HEIGHT:-480}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_HEIGHT:-480}"));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user