Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
apt-get update
apt-get install -y \
git build-essential cmake pkg-config \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev \
libsqlite3-dev libuv1-dev libllhttp-dev libcurl4-openssl-dev \
libcjson-dev libmbedtls-dev libmosquitto-dev

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/debian-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,12 @@ jobs:
# ── Suite-specific FFmpeg dependency names ─────────────────────────
case "${DEBIAN_SUITE}" in
sid)
FFMPEG_DEPS="libavcodec62 | libavcodec-extra, libavformat62, libavutil60, libswscale9"
FFMPEG_DEPS="libavcodec62 | libavcodec-extra, libavformat62, libavutil60, libswscale9, libavfilter11"
LLHTTP_DEP="libllhttp9.3"
SUITE_NOTE="Note: This package targets Debian sid (unstable)."
;;
trixie)
FFMPEG_DEPS="libavcodec61 | libavcodec-extra, libavformat61, libavutil59, libswscale8"
FFMPEG_DEPS="libavcodec61 | libavcodec-extra, libavformat61, libavutil59, libswscale8, libavfilter10"
LLHTTP_DEP="libllhttp9.2"
SUITE_NOTE="Note: This package targets Debian 13 trixie (stable)."
;;
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jobs:
libavformat-dev \
libavutil-dev \
libswscale-dev \
libavfilter-dev \
libsqlite3-dev \
libuv1-dev \
libllhttp-dev \
Expand Down Expand Up @@ -118,6 +119,11 @@ jobs:
test_onvif_soap_fault \
test_faac_encoder \
test_audio_transcoder \
test_audio_voice_enhancement \
test_audio_voice_filter_faults \
test_udt_recording \
test_detection_current_frame \
test_detection_io_recovery \
test_hls_cleanup \
test_stream_manager \
test_stream_state \
Expand All @@ -133,7 +139,7 @@ jobs:
run: |
cd build
ctest --output-on-failure -V \
-R "test_storage_pressure$|test_storage_pressure_extended|test_detection_result_structures|test_storage_retention_sqlite|test_storage_manager_retention|test_storage_target_pressure_cleanup|test_storage_migration|test_storage_archive_s3|test_storage_archive_operator|test_authorization|test_api_handlers_recordings_playback|test_db_storage_targets|test_db_storage_policies|test_api_handlers_storage_targets|test_api_handlers_storage_policies|test_config|test_logger|test_strings|test_memory|test_request_response|test_shutdown_coordinator|test_detection_config|test_detection_model_motion|test_db_streams|test_db_camera_favorites|test_api_handlers_camera_favorites|test_db_backup|test_mp4_failed_open_memory|test_db_recordings_extended|test_db_detections|test_db_zones|test_db_events|test_db_auth|test_db_transactions|test_db_maintenance|test_db_query_builder|test_logger_json|test_batch_delete_progress|test_db_recordings_sync|test_httpd_utils|test_zone_filter|test_onvif_soap_fault|test_faac_encoder|test_audio_transcoder|test_hls_cleanup|test_stream_manager|test_stream_state|test_packet_buffer|test_timestamp_manager|test_motion_trigger_parse|test_motion_max_area|test_url_utils"
-R "test_storage_pressure$|test_storage_pressure_extended|test_detection_result_structures|test_storage_retention_sqlite|test_storage_manager_retention|test_storage_target_pressure_cleanup|test_storage_migration|test_storage_archive_s3|test_storage_archive_operator|test_authorization|test_api_handlers_recordings_playback|test_db_storage_targets|test_db_storage_policies|test_api_handlers_storage_targets|test_api_handlers_storage_policies|test_config|test_logger|test_strings|test_memory|test_request_response|test_shutdown_coordinator|test_detection_config|test_detection_model_motion|test_db_streams|test_db_camera_favorites|test_api_handlers_camera_favorites|test_db_backup|test_mp4_failed_open_memory|test_db_recordings_extended|test_db_detections|test_db_zones|test_db_events|test_db_auth|test_db_transactions|test_db_maintenance|test_db_query_builder|test_logger_json|test_batch_delete_progress|test_db_recordings_sync|test_httpd_utils|test_zone_filter|test_onvif_soap_fault|test_faac_encoder|test_audio_transcoder|test_audio_voice_enhancement|test_audio_voice_filter_faults|test_udt_recording|test_detection_current_frame|test_detection_io_recovery|test_hls_cleanup|test_stream_manager|test_stream_state|test_packet_buffer|test_timestamp_manager|test_motion_trigger_parse|test_motion_max_area|test_url_utils"

- name: Generate coverage report
if: always()
Expand Down Expand Up @@ -213,6 +219,7 @@ jobs:
libavformat-dev \
libavutil-dev \
libswscale-dev \
libavfilter-dev \
libswresample-dev \
libsqlite3-dev \
libuv1-dev \
Expand Down Expand Up @@ -378,6 +385,7 @@ jobs:
libavformat-dev \
libavutil-dev \
libswscale-dev \
libavfilter-dev \
libsqlite3-dev \
libuv1-dev \
libllhttp-dev \
Expand Down Expand Up @@ -508,6 +516,7 @@ jobs:
libavformat-dev \
libavutil-dev \
libswscale-dev \
libavfilter-dev \
libsqlite3-dev \
libuv1-dev \
libllhttp-dev \
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/sanitizer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
apt-get update
apt-get install -y \
git build-essential cmake pkg-config python3 \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev \
libsqlite3-dev libuv1-dev libllhttp-dev libcurl4-openssl-dev \
libcjson-dev libmbedtls-dev

Expand Down Expand Up @@ -60,7 +60,7 @@ jobs:
cd build
echo "Running tests with ASan + UBSan enabled..."
ctest --output-on-failure -V \
-R "test_config|test_logger|test_strings|test_memory|test_request_response|test_shutdown_coordinator|test_detection_config|test_detection_model_motion|test_db_streams|test_db_recordings_extended|test_db_detections|test_db_zones|test_db_events|test_db_auth|test_db_transactions|test_db_maintenance|test_db_query_builder|test_logger_json|test_batch_delete_progress|test_db_recordings_sync|test_httpd_utils|test_zone_filter|test_faac_encoder|test_audio_transcoder|test_stream_manager|test_stream_state|test_packet_buffer|test_timestamp_manager|test_storage_pressure$|test_storage_pressure_extended|test_detection_result_structures|test_storage_retention_sqlite|test_audit_log|test_audit_summary"
-R "test_config|test_logger|test_strings|test_memory|test_request_response|test_shutdown_coordinator|test_detection_config|test_detection_model_motion|test_db_streams|test_db_recordings_extended|test_db_detections|test_db_zones|test_db_events|test_db_auth|test_db_transactions|test_db_maintenance|test_db_query_builder|test_logger_json|test_batch_delete_progress|test_db_recordings_sync|test_httpd_utils|test_zone_filter|test_faac_encoder|test_audio_transcoder|test_audio_voice_enhancement|test_audio_voice_filter_faults|test_udt_recording|test_detection_current_frame|test_detection_io_recovery|test_stream_manager|test_stream_state|test_packet_buffer|test_timestamp_manager|test_storage_pressure$|test_storage_pressure_extended|test_detection_result_structures|test_storage_retention_sqlite|test_audit_log|test_audit_summary"

- name: Smoke test - start and stop service
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
apt-get update
apt-get install -y \
git build-essential cmake pkg-config clang-tidy \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev \
libsqlite3-dev libuv1-dev libllhttp-dev libcurl4-openssl-dev \
libcjson-dev libmbedtls-dev libmosquitto-dev

Expand Down
27 changes: 27 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,24 @@ else()
message(WARNING "libyaml (yaml-0.1) not found. YAML validation and go2rtc override base_path detection will be disabled. Install libyaml-dev / yaml-dev to enable.")
endif()

# libavfilter (optional) — per-stream voice-enhancement filter chain applied
# while transcoding PCM audio to AAC (issue #652). Without it the opt-in is
# accepted but logs that it is unavailable. The afftdn denoiser is the costly
# stage, so the embedded profile leaves it out by default.
option(ENABLE_AUDIO_FILTERS "Enable libavfilter audio filters (voice enhancement)" ON)
option(ENABLE_AUDIO_DENOISE "Include the afftdn denoiser in voice enhancement" ${LIGHTNVR_OPTIONAL_FEATURE_DEFAULT})
if(ENABLE_AUDIO_FILTERS)
pkg_check_modules(AVFILTER QUIET libavfilter>=10)
if(AVFILTER_FOUND)
message(STATUS "Found libavfilter: ${AVFILTER_VERSION} (denoise: ${ENABLE_AUDIO_DENOISE})")
add_compile_definitions(LIGHTNVR_HAVE_AVFILTER=1
LIGHTNVR_AUDIO_DENOISE=$<BOOL:${ENABLE_AUDIO_DENOISE}>)
else()
message(WARNING "libavfilter >= 10 not found. Voice enhancement will be unavailable. Install libavfilter-dev to enable.")
set(ENABLE_AUDIO_FILTERS OFF)
endif()
endif()

# MQTT support (optional, uses libmosquitto)
option(ENABLE_MQTT "Enable MQTT support for detection event streaming" ${LIGHTNVR_OPTIONAL_FEATURE_DEFAULT})
if(ENABLE_MQTT)
Expand Down Expand Up @@ -760,6 +778,15 @@ if(YAML_FOUND)
target_link_libraries(lightnvr ${YAML_LIBRARIES})
endif()

# Link libavfilter if enabled (voice enhancement)
if(ENABLE_AUDIO_FILTERS AND AVFILTER_FOUND)
if(AVFILTER_LIBRARY_DIRS)
target_link_directories(lightnvr_lib PUBLIC ${AVFILTER_LIBRARY_DIRS})
endif()
target_link_libraries(lightnvr_lib PUBLIC ${AVFILTER_LIBRARIES})
target_include_directories(lightnvr_lib PUBLIC ${AVFILTER_INCLUDE_DIRS})
endif()

# Link MQTT library if enabled
if(ENABLE_MQTT AND MOSQUITTO_FOUND)
if(MOSQUITTO_LIBRARY_DIRS)
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ RUN if [ "$TARGETARCH/$TARGETVARIANT" = "arm/v7" ]; then \
test -n "$GCC_MAJOR" && \
apt-get install -y --no-install-recommends \
"libstdc++-${GCC_MAJOR}-dev" \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev \
libcurl4-openssl-dev libmbedtls-dev libcjson-dev \
libmosquitto-dev libyaml-dev && \
if [ "$DEB_BUILD" = "true" ]; then \
Expand Down Expand Up @@ -104,7 +104,7 @@ RUN if [ "$TARGETARCH/$TARGETVARIANT" = "arm/v7" ]; then \
rm /tmp/armv7-toolchain-check; \
else \
apt-get install -y --no-install-recommends \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev \
libcurl4-openssl-dev libmbedtls-dev libcjson-dev \
libmosquitto-dev libyaml-dev; \
fi && \
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ Powerful object detection using modern ONNX and TFLite models with zone-aware fi

Prerequisites (in addition to `build-essential`, `cmake`, `pkg-config`):
- **FFmpeg ≥ 7.1** (`libavcodec ≥ 61`, `libavformat ≥ 61`, `libavutil ≥ 59`,
`libswscale ≥ 8`, `libswresample ≥ 5`). Debian 12 (bookworm) and Ubuntu
`libswscale ≥ 8`, `libswresample ≥ 5`; optional `libavfilter ≥ 10` for
per-stream voice enhancement). Debian 12 (bookworm) and Ubuntu
22.04 ship FFmpeg 5.x/6.x, which is too old — build FFmpeg from source or
use a newer distro release (Debian 13 / Ubuntu 24.04+ ship a compatible
version).
Expand Down
27 changes: 24 additions & 3 deletions docs/BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ sudo apt-get install -y \
libavformat-dev \
libavutil-dev \
libswscale-dev \
libavfilter-dev \
libcurl4-openssl-dev \
libmbedtls-dev \
curl \
Expand Down Expand Up @@ -104,6 +105,25 @@ When built without SOD, LightNVR will still function normally but will not have

For more information about SOD integration, see [SOD Integration](SOD_INTEGRATION.md).

### Voice enhancement (libavfilter)

The per-stream **Voice Enhancement** option filters recorded audio while it is
transcoded from PCM (G.711 μ-law/A-law, raw PCM) to AAC: two cascaded
`highpass=f=100` sections for hum and rumble, `lowpass=f=8000` when the source
rate carries content above 8 kHz, and the `afftdn` adaptive denoiser. It needs
`libavfilter` (`libavfilter-dev`):

- `ENABLE_AUDIO_FILTERS` (default `ON`) links libavfilter when pkg-config finds
it. When it is missing or disabled, the build still succeeds and turning the
option on logs that it is unavailable; audio records unfiltered.
- `ENABLE_AUDIO_DENOISE` (default `ON`, `OFF` in the embedded profile) includes
`afftdn`, the CPU-heavy stage. With it off, only the highpass/lowpass run.

Audio that the camera already sends in an MP4-compatible codec (AAC, MP3,
Opus, AC-3) is passed through to the recording without re-encoding, and is
**not** filtered. Live audio is never filtered. If the filter graph cannot be
built, LightNVR logs a warning once and keeps recording unfiltered audio.

### Embedded build profile

Resource-constrained targets can select the embedded profile without changing
Expand All @@ -117,9 +137,10 @@ cmake --build build/embedded -- -j$(nproc)
```

The embedded profile caps compile-time stream storage at 16 streams, optimizes
for size, and defaults SOD, LiteRT, and MQTT off. The individual feature
switches remain available when an embedded target needs one of them. Full
builds remain the default and retain the 1024-stream ceiling.
for size, and defaults SOD, LiteRT, MQTT, and the voice-enhancement denoiser
(`ENABLE_AUDIO_DENOISE`) off. The individual feature switches remain available
when an embedded target needs one of them. Full builds remain the default and
retain the 1024-stream ceiling.

`LIGHTNVR_MAX_STREAMS` can override the full-profile ceiling. Embedded builds
accept values from 1 through 16 only. The older `EMBEDDED_A1_DEVICE=ON` option
Expand Down
2 changes: 2 additions & 0 deletions docs/INSTALLATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ sudo apt-get install -y \
libavformat-dev \
libavutil-dev \
libswscale-dev \
libavfilter-dev \
libuv1-dev \
libcurl4-openssl-dev \
libmbedtls-dev \
Expand Down Expand Up @@ -420,6 +421,7 @@ sudo apt-get install -y \
libavformat-dev \
libavutil-dev \
libswscale-dev \
libavfilter-dev \
libuv1-dev \
libcurl4-openssl-dev \
libmbedtls-dev \
Expand Down
1 change: 1 addition & 0 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ sudo apt-get install -y \
libavformat-dev \
libavutil-dev \
libswscale-dev \
libavfilter-dev \
libuv1-dev \
libcurl4-openssl-dev \
libssl-dev
Expand Down
1 change: 1 addition & 0 deletions include/video/unified_detection_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ typedef struct {

// Audio recording configuration
bool record_audio; // Whether to include audio in recordings
bool audio_voice_enhancement; // Voice-enhancement filter for transcoded PCM audio

// External motion trigger: set to 1 by unified_detection_notify_motion() when
// an ONVIF-managed master stream propagates its motion event to this UDT-managed
Expand Down
Loading
Loading