Skip to content

Commit 8e04da1

Browse files
committed
Introduce Dahua CGI source for 2-way audio
1 parent 34b103b commit 8e04da1

File tree

7 files changed

+650
-0
lines changed

7 files changed

+650
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.idea/
22
.tmp/
33

4+
go2rtc
45
go2rtc.yaml
56
go2rtc.json
67

@@ -12,3 +13,7 @@ go2rtc_win*
1213
0_test.go
1314

1415
.DS_Store
16+
17+
*.mp3
18+
*.wav
19+
*.al

fix_vto_codecs.sh

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/bin/bash
2+
#
3+
# This script fixes the VTO audio codecs before supplying the stream url to go2rtc.
4+
#
5+
# Usage: ./fix_vto_codecs.sh [--debug] [--https] <VTO stream URL>
6+
#
7+
# Examples:
8+
#
9+
# ./fix_vto_codecs.sh rtsp://user:[email protected]/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
10+
# ./fix_vto_codecs.sh rtsp://user:[email protected]/cam/realmonitor?channel=1&subtype=1
11+
#
12+
# If the VTO has HTTPS enabled:
13+
# ./fix_vto_codecs.sh --https rtsp://user:[email protected]/cam/realmonitor?channel=1&subtype=0
14+
#
15+
# With ffmpeg prefix:
16+
# ./fix_vto_codecs.sh ffmpeg:rtsp://user:[email protected]/cam/realmonitor?channel=1&subtype=0#video=copy#audio=copy
17+
#
18+
19+
set -euo pipefail
20+
21+
usage() {
22+
echo "Usage: ${0} [--debug] [--https] <VTO stream URL>" >&2
23+
exit "${1}"
24+
}
25+
26+
debug=false
27+
protocol="http"
28+
extra_curl_args=()
29+
30+
positional_args=()
31+
while [[ $# -gt 0 ]]; do
32+
case $1 in
33+
--debug)
34+
debug=true
35+
shift
36+
;;
37+
--https)
38+
protocol="https"
39+
extra_curl_args+=("--insecure")
40+
shift
41+
;;
42+
-*)
43+
echo "Unknown option ${1}" >&2
44+
usage 1
45+
;;
46+
*)
47+
positional_args+=("$1")
48+
shift
49+
;;
50+
esac
51+
done
52+
53+
set -- "${positional_args[@]}"
54+
unset positional_args
55+
56+
if [[ $# -ne 1 ]]; then
57+
echo "Expected 1 positional argument, got $#" >&2
58+
usage 1
59+
fi
60+
61+
vto_stream_url="${1}"
62+
63+
if [[ "${vto_stream_url}" != "rtsp://"* && "${vto_stream_url}" != "ffmpeg:rtsp://"* ]]; then
64+
echo "VTO stream URL does not start with rtsp:// or ffmpeg:rtsp://" >&2
65+
usage 1
66+
fi
67+
68+
if [[ "${debug}" == "true" ]]; then
69+
set -x
70+
extra_curl_args+=("--verbose")
71+
fi
72+
73+
vto_host_with_creds="${vto_stream_url#"ffmpeg:"}"
74+
vto_host_with_creds="${vto_host_with_creds#"rtsp://"}"
75+
vto_host_with_creds="${vto_host_with_creds%%"/"*}"
76+
if [[ "${vto_host_with_creds}" =~ :[0-9]+$ ]]; then
77+
vto_host_with_creds="${vto_host_with_creds%":"*}"
78+
fi
79+
80+
query="action=setConfig"
81+
# PCMA: average audio quality, but good for WebRTC and 2-way audio
82+
query+="&Encode[0].MainFormat[0].Audio.Compression=G.711A"
83+
# 16000Hz yields better audio quality, but try 8000Hz if your VTO does not support it
84+
query+="&Encode[0].MainFormat[0].Audio.Frequency=8000"
85+
# AAC: best audio quality, good for Frigate recordings
86+
query+="&Encode[0].ExtraFormat[0].Audio.Compression=AAC"
87+
88+
# PS: the current config can be retrieved with:
89+
# curl -fsSL --digest --globoff \
90+
# http://user:[email protected]/cgi-bin/configManager.cgi?action=getConfig&name=Encode
91+
92+
output=$(
93+
curl --fail --silent --show-error --digest --globoff "${extra_curl_args[@]}" \
94+
"${protocol}://${vto_host_with_creds}/cgi-bin/configManager.cgi?${query}"
95+
)
96+
97+
if [[ "${output}" != $'OK\r' ]]; then
98+
echo "Failed to set VTO codecs. Response:" >&2
99+
echo "${output}" >&2
100+
exit 1
101+
fi
102+
103+
echo -n "${vto_stream_url}"

internal/dahua/init.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package dahua
2+
3+
import (
4+
"github.com/AlexxIT/go2rtc/internal/streams"
5+
"github.com/AlexxIT/go2rtc/pkg/core"
6+
"github.com/AlexxIT/go2rtc/pkg/dahua"
7+
)
8+
9+
func Init() {
10+
streams.HandleFunc("dahua", func(source string) (core.Producer, error) {
11+
return dahua.Dial(source)
12+
})
13+
}

main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/AlexxIT/go2rtc/internal/api/ws"
77
"github.com/AlexxIT/go2rtc/internal/app"
88
"github.com/AlexxIT/go2rtc/internal/bubble"
9+
"github.com/AlexxIT/go2rtc/internal/dahua"
910
"github.com/AlexxIT/go2rtc/internal/debug"
1011
"github.com/AlexxIT/go2rtc/internal/doorbird"
1112
"github.com/AlexxIT/go2rtc/internal/dvrip"
@@ -84,6 +85,7 @@ func main() {
8485
dvrip.Init() // dvrip source
8586
tapo.Init() // tapo source
8687
isapi.Init() // isapi source
88+
dahua.Init() // dahua source
8789
mpegts.Init() // mpegts passive source
8890
roborock.Init() // roborock source
8991
homekit.Init() // homekit source

pkg/dahua/CGI_SDK_API.txt

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
11. Audio
2+
3+
11.1 Audio MIME type
4+
5+
MIME Description
6+
Audio/PCM
7+
Audio/ADPCM
8+
Audio/G.711A
9+
Audio/G.711Mu
10+
Audio/G.726
11+
Audio/G.729
12+
13+
92
14+
Audio/MPEG2
15+
Audio/AMR
16+
Audio/AAC
17+
18+
19+
20+
11.2 Post Audio
21+
22+
URL Syntax http://<ip>/cgi-bin/audio.cgi?action=postAudio&<paramName>=<paramValue>[&<paramName>=<paramValue>...]
23+
Comment paramValue as below table.
24+
Response OK or ERROR
25+
26+
27+
ParamName ParamValue type Description
28+
httptype string singlepart:HTTP content is a continuous flow of audio
29+
packets
30+
multipart:HTTP content type is
31+
multipart/x-mixed-replace,and each audio packet ends
32+
with a boundary string
33+
channel integer The audio channel
34+
35+
36+
37+
11.2.1 Example for singlepart
38+
39+
The RUL of transmit a singlepart、channel 1 audio stream(encoded with G.711 A-law) is:
40+
http: //<ip>/cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1
41+
42+
43+
example:
44+
POST /cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1 HTTP/1.1
45+
Content-Type: Audio/G.711A
46+
Content-Length:9999999
47+
48+
49+
<Audio data>
50+
<Audio data>
51+
52+
53+
54+
11.2.2 Example for multipart
55+
56+
The RUL of transmit a multipart、channel 1 audio stream(encoded with G.711 A-law) is:
57+
http: //<ip>/cgi-bin/audio.cgi?action=postAudio&httptype= multipart &channel=1
58+
59+
60+
example:
61+
POST /cgi-bin/audio.cgi?action=postAudio&httptype= multipart &channel=1 HTTP/1.1
62+
Content-Type: multipart/x-mixed-replace; boundary=<boundary>
63+
--<boundary>
64+
Content-Type: Audio/G.711A
65+
66+
93
67+
Content-Length: 800
68+
69+
70+
<Audio data>
71+
--<boundary>
72+
73+
74+
75+
11.3 Get Audio
76+
77+
URL Syntax http://<ip>/cgi-bin/audio.cgi?action=getAudio&<paramName>=<paramValue>[&<paramName>=<paramValue>...]
78+
Comment paramValue as below table.
79+
Response OK or ERROR
80+
81+
82+
83+
84+
ParamName ParamValue type Description
85+
httptype string singlepart:HTTP content is a continuous flow of audio
86+
packets
87+
multipart:HTTP content type is
88+
multipart/x-mixed-replace,and each audio packet ends
89+
with a boundary string
90+
channel integer The audio channel
91+
92+
93+
94+
95+
11.3.1 Example for singlepart
96+
97+
The RUL of Request a singlepart、channel 1 audio stream(encoded with G.711 A-law) is:
98+
http: //<ip>/cgi-bin/audio.cgi?action=getAudio&httptype=singlepart&channel=1
99+
100+
101+
If the request was successful, the server returns a continuous flow of audio packets.The content type is only set at the beginning of the
102+
connection.
103+
Return:
104+
HTTP Code: 200 OK
105+
Content-Type: Audio/G.711A
106+
Body:
107+
<Audio data>
108+
<Audio data>
109+
110+
111+
112+
11.3.2 Example for multipart
113+
114+
The RUL of Request a multipart、channel 1 audio stream(encoded with G.711 A-law) is:
115+
http: //<ip>/cgi-bin/audio.cgi?action=getAudio&httptype=multipart&channel=1
116+
117+
118+
If the request was successful, the server returns a continuous flow of audio packets. The content type is “multipart/x-mixed-replace” and each
119+
audio packet ends with a boundary string.
120+
94
121+
Return:
122+
HTTP Code: 200 OK
123+
Content-Type: multipart/x-mixed-replace; boundary=<boundary>
124+
--<boundary>
125+
Content-Type: Audio/G.711A
126+
Content-Length: 800
127+
128+
129+
<Audio data>
130+
--<boundary>
131+
132+
133+
134+
135+
11.4 Audio Input
136+
137+
11.4.1 getCollect
138+
139+
URL Syntax http://<ip>/cgi-bin/devAudioInput.cgi?action=getCollect
140+
Comment Get Audio input channel number.
141+
Below response means there are 2 audio input channels.
142+
Response result=2
143+
144+
145+
146+
147+
11.5 Audio Output
148+
149+
11.5.1 getCollect
150+
151+
URL Syntax http://<ip>/cgi-bin/devAudioOutput.cgi?action=getCollect
152+
Comment Get Audio output channel number.
153+
Below response means there are 2 audio output channels.
154+
Response result=2

0 commit comments

Comments
 (0)