diff --git a/.gitignore b/.gitignore index 52fe9c864..4df4e49be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea/ .tmp/ +go2rtc go2rtc.yaml go2rtc.json @@ -12,3 +13,7 @@ go2rtc_win* 0_test.go .DS_Store + +*.mp3 +*.wav +*.al diff --git a/fix_vto_codecs.sh b/fix_vto_codecs.sh new file mode 100755 index 000000000..fd3789926 --- /dev/null +++ b/fix_vto_codecs.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# +# This script fixes the VTO audio codecs before supplying the stream url to go2rtc. +# +# Usage: ./fix_vto_codecs.sh [--debug] [--https] +# +# Examples: +# +# ./fix_vto_codecs.sh rtsp://user:pass@192.168.1.40/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif +# ./fix_vto_codecs.sh rtsp://user:pass@192.168.1.40/cam/realmonitor?channel=1&subtype=1 +# +# If the VTO has HTTPS enabled: +# ./fix_vto_codecs.sh --https rtsp://user:pass@192.168.1.40/cam/realmonitor?channel=1&subtype=0 +# +# With ffmpeg prefix: +# ./fix_vto_codecs.sh ffmpeg:rtsp://user:pass@192.168.1.40/cam/realmonitor?channel=1&subtype=0#video=copy#audio=copy +# + +set -euo pipefail + +usage() { + echo "Usage: ${0} [--debug] [--https] " >&2 + exit "${1}" +} + +debug=false +protocol="http" +extra_curl_args=() + +positional_args=() +while [[ $# -gt 0 ]]; do + case $1 in + --debug) + debug=true + shift + ;; + --https) + protocol="https" + extra_curl_args+=("--insecure") + shift + ;; + -*) + echo "Unknown option ${1}" >&2 + usage 1 + ;; + *) + positional_args+=("$1") + shift + ;; + esac +done + +set -- "${positional_args[@]}" +unset positional_args + +if [[ $# -ne 1 ]]; then + echo "Expected 1 positional argument, got $#" >&2 + usage 1 +fi + +vto_stream_url="${1}" + +if [[ "${vto_stream_url}" != "rtsp://"* && "${vto_stream_url}" != "ffmpeg:rtsp://"* ]]; then + echo "VTO stream URL does not start with rtsp:// or ffmpeg:rtsp://" >&2 + usage 1 +fi + +if [[ "${debug}" == "true" ]]; then + set -x + extra_curl_args+=("--verbose") +fi + +vto_host_with_creds="${vto_stream_url#"ffmpeg:"}" +vto_host_with_creds="${vto_host_with_creds#"rtsp://"}" +vto_host_with_creds="${vto_host_with_creds%%"/"*}" +if [[ "${vto_host_with_creds}" =~ :[0-9]+$ ]]; then + vto_host_with_creds="${vto_host_with_creds%":"*}" +fi + +query="action=setConfig" +# PCMA: average audio quality, but good for WebRTC and 2-way audio +query+="&Encode[0].MainFormat[0].Audio.Compression=G.711A" +# 16000Hz yields better audio quality, but try 8000Hz if your VTO does not support it +query+="&Encode[0].MainFormat[0].Audio.Frequency=8000" +# AAC: best audio quality, good for Frigate recordings +query+="&Encode[0].ExtraFormat[0].Audio.Compression=AAC" + +# PS: the current config can be retrieved with: +# curl -fsSL --digest --globoff \ +# http://user:pass@192.168.1.40/cgi-bin/configManager.cgi?action=getConfig&name=Encode + +output=$( + curl --fail --silent --show-error --digest --globoff "${extra_curl_args[@]}" \ + "${protocol}://${vto_host_with_creds}/cgi-bin/configManager.cgi?${query}" +) + +if [[ "${output}" != $'OK\r' ]]; then + echo "Failed to set VTO codecs. Response:" >&2 + echo "${output}" >&2 + exit 1 +fi + +echo -n "${vto_stream_url}" diff --git a/internal/dahua/init.go b/internal/dahua/init.go new file mode 100644 index 000000000..6428b1c15 --- /dev/null +++ b/internal/dahua/init.go @@ -0,0 +1,13 @@ +package dahua + +import ( + "github.com/AlexxIT/go2rtc/internal/streams" + "github.com/AlexxIT/go2rtc/pkg/core" + "github.com/AlexxIT/go2rtc/pkg/dahua" +) + +func Init() { + streams.HandleFunc("dahua", func(source string) (core.Producer, error) { + return dahua.Dial(source) + }) +} diff --git a/main.go b/main.go index e85c5900f..5cf788118 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "github.com/AlexxIT/go2rtc/internal/api/ws" "github.com/AlexxIT/go2rtc/internal/app" "github.com/AlexxIT/go2rtc/internal/bubble" + "github.com/AlexxIT/go2rtc/internal/dahua" "github.com/AlexxIT/go2rtc/internal/debug" "github.com/AlexxIT/go2rtc/internal/doorbird" "github.com/AlexxIT/go2rtc/internal/dvrip" @@ -84,6 +85,7 @@ func main() { dvrip.Init() // dvrip source tapo.Init() // tapo source isapi.Init() // isapi source + dahua.Init() // dahua source mpegts.Init() // mpegts passive source roborock.Init() // roborock source homekit.Init() // homekit source diff --git a/pkg/dahua/CGI_SDK_API.txt b/pkg/dahua/CGI_SDK_API.txt new file mode 100644 index 000000000..9a96878d9 --- /dev/null +++ b/pkg/dahua/CGI_SDK_API.txt @@ -0,0 +1,154 @@ +11. Audio + +11.1 Audio MIME type + +MIME Description +Audio/PCM +Audio/ADPCM +Audio/G.711A +Audio/G.711Mu +Audio/G.726 +Audio/G.729 + + 92 +Audio/MPEG2 +Audio/AMR +Audio/AAC + + + +11.2 Post Audio + +URL Syntax http:///cgi-bin/audio.cgi?action=postAudio&=[&=...] +Comment paramValue as below table. +Response OK or ERROR + + +ParamName ParamValue type Description +httptype string singlepart:HTTP content is a continuous flow of audio + packets + multipart:HTTP content type is + multipart/x-mixed-replace,and each audio packet ends + with a boundary string +channel integer The audio channel + + + +11.2.1 Example for singlepart + +The RUL of transmit a singlepart、channel 1 audio stream(encoded with G.711 A-law) is: +http: ///cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1 + + +example: +POST /cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1 HTTP/1.1 +Content-Type: Audio/G.711A +Content-Length:9999999 + + +