Further investigation has disclosed that the AD410 doorbell camera has an even more-serious issue that precludes running outbound ("speak") audio to the speaker at all, except through their app which apparently is using a back-channel authenticated RTSP stream I've not been able to intercept successfully as of yet (that is, even if you use the app and you're in the same building its not going directly to the camera) and that is likely unable to be intercepted at all because their AWS-based server (with which its talking) is sending encrypted traffic, so determining exactly what it is sending is not possible (e.g. is it sending a POST, is it using back-channel RTSP -- not sure.)
That is the AD410 refuses BASIC authentication on a POST and demands DIGEST. That's fine
except that the way this works generally is that the first request comes back with an "Unauthorized" response and the nonce, qop and such you need to compute the digest. Fine, you do that and send the content
but on that second request the camera does indeed accept it and send back an "ok" immediately after swallowing the number of bytes you specified to be transferred (good)
but then since you got the reply back your end will close the connection and as soon as you do the speech is terminated.
The result is that all you get is the "click" if the speaker unmuting AND NEVER THE ACTUAL SPEECH.
There may also be a problem with it refusing to honor the codec but I can't be sure about that -- all I get is the "click" and not "random noise" (which is what happens with a codec mismatch.)
Thus while I now have "working" (albeit with a serious bit of stupidity in their code I have to work around) for the subject cameras (and presumably anything else that's an indoor with a speaker)
that doesn't work for the doorbell even though the http server on the doorbell says it did, and exactly why is not clear since the doorbell SAYS it is happy with the transmission.
Traceback from said test:
Code: Select all
$ ./test-curl test.amr
ffmpeg version 6.1.1 Copyright (c) 2000-2023 the FFmpeg developers
built with FreeBSD clang version 16.0.6 (https://github.com/llvm/llvm-project.git llvmorg-16.0.6-0-g7cbf1a259152)
configuration: --prefix=/usr/local --mandir=/usr/local/share/man --datadir=/usr/local/share/ffmpeg --docdir=/usr/local/share/doc/ffmpeg --pkgconfigdir=/usr/local/libdata/pkgconfig --disable-static --disable-libcelt --enable-shared --enable-pic --enable-gpl --cc=cc --cxx=c++ --disable-alsa --disable-libopencore-amrnb --disable-libopencore-amrwb --enable-libaom --disable-libaribb24 --disable-libaribcaption --enable-asm --enable-libass --disable-libbs2b --disable-libcaca --disable-libcdio --disable-libcodec2 --enable-libdav1d --disable-libdavs2 --disable-libdc1394 --disable-debug --enable-htmlpages --enable-libdrm --disable-libfdk-aac --disable-libflite --enable-fontconfig --enable-libfreetype --enable-frei0r --disable-libfribidi --disable-gcrypt --disable-libglslang --disable-libgme --enable-gmp --enable-gnutls --enable-version3 --disable-libgsm --enable-libharfbuzz --enable-iconv --disable-libilbc --disable-libjack --enable-libjxl --disable-libklvanc --disable-libkvazaar --disable-ladspa --enable-libmp3lame --enable-lcms2 --disable-liblensfun --disable-libbluray --enable-libplacebo --disable-librsvg --enable-libxml2 --disable-lv2 --disable-mbedtls --disable-libmodplug --disable-libmysofa --enable-network --disable-nonfree --disable-nvenc --disable-openal --disable-opencl --disable-opengl --disable-libopenh264 --disable-libopenjpeg --disable-libopenmpt --disable-openssl --disable-libopenvino --enable-optimizations --enable-libopus --disable-pocketsphinx --disable-libpulse --disable-librabbitmq --disable-librav1e --disable-librist --enable-runtime-cpudetect --disable-librubberband --disable-sdl2 --enable-libshaderc --disable-libsmbclient --disable-libsnappy --disable-sndio --disable-libsoxr --disable-libspeex --disable-libsrt --disable-libssh --enable-libsvtav1 --disable-libtensorflow --disable-libtesseract --disable-libtheora --disable-libtwolame --disable-libuavs3d --enable-libv4l2 --enable-vaapi --disable-vapoursynth --enable-vdpau --disable-libvidstab --enable-libvmaf --enable-libvorbis --disable-libvo-amrwbenc --enable-libvpx --enable-vulkan --enable-libwebp --enable-libx264 --enable-libx265 --disable-libxavs2 --enable-libxcb --disable-libxvid --disable-outdev=xv --disable-libzimg --disable-libzmq --disable-libzvbi
libavutil 58. 29.100 / 58. 29.100
libavcodec 60. 31.102 / 60. 31.102
libavformat 60. 16.100 / 60. 16.100
libavdevice 60. 3.100 / 60. 3.100
libavfilter 9. 12.100 / 9. 12.100
libswscale 7. 5.100 / 7. 5.100
libswresample 4. 12.100 / 4. 12.100
libpostproc 57. 3.100 / 57. 3.100
Input #0, amr, from 'pipe:':
Duration: N/A, bitrate: 12 kb/s
Stream #0:0: Audio: amr_nb (samr / 0x726D6173), 8000 Hz, mono, fltp, 12 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (amr_nb (amrnb) -> pcm_alaw (native))
Output #0, alaw, to 'pipe:':
Metadata:
encoder : Lavf60.16.100
Stream #0:0: Audio: pcm_alaw, 8000 Hz, mono, s16, 64 kb/s
Metadata:
encoder : Lavc60.31.102 pcm_alaw
[out#0/alaw @ 0x391d8ce24180] video:0kB audio:14kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
size= 14kB time=00:00:01.78 bitrate= 64.7kbits/s speed= 112x
This shows we took an AMR file and turned it into G.711A alaw stream; this same stream plays perfectly well on the subject cameras
however as noted above those cameras only take BASIC authentication and hang without returning a status once the upload is complete, so you need the timeout. The AD410 doorbell behaves differently with the same API call:
Code: Select all
* Trying 192.168.4.126:80...
* Connected to 192.168.4.126 (192.168.4.126) port 80
> POST /cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1 HTTP/1.1
Host: 192.168.4.126
Accept: */*
Content-Type: Audio/G.711A
Content-Length: 14400
* upload completely sent off: 14400 bytes
< HTTP/1.1 401 Unauthorized
< WWW-Authenticate: Digest realm="Login to Z1738F183FEF6", qop="auth", nonce="587431416", opaque="37a266f79d50f73e70e91f40b038d5294157eea9"
< Connection: close
< CONTENT-LENGTH: 0
<
The AD410 says "Gimme DIGEST authentication" as per the standard. Good, so the curl library will do that.
Code: Select all
* Need to rewind upload for next request
* Closing connection
* Issue another request to this URL: 'http://192.168.4.126/cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1'
* Hostname 192.168.4.126 was found in DNS cache
* Trying 192.168.4.126:80...
* Connected to 192.168.4.126 (192.168.4.126) port 80
* Server auth using Digest with user 'admin'
> POST /cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1 HTTP/1.1
Host: 192.168.4.126
Authorization: Digest username="admin", realm="Login to Z1738F183FEF6", nonce="587431416", uri="/cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1", cnonce="MWMxNTY2OTRlNjM3YWZjNmNhOGUxMDhkNzQ4NzJmYjc=", nc=00000001, qop=auth, response="81cd8b521b7d46fca91b9ddc2266dfff", opaque="37a266f79d50f73e70e91f40b038d5294157eea9"
Accept: */*
Content-Type: Audio/G.711A
Content-Length: 14400
* upload completely sent off: 14400 bytes
< HTTP/1.1 200 OK
< X-XSS-Protection: 1;mode=block
< X-Frame-Options: SAMEORIGIN
< Content-Security-Policy: script-src 'self' 'unsafe-inline' 'unsafe-eval'
< Strict-Transport-Security: max-age=604800; includeSubDomains
< CONNECTION: Keep-Alive
< CONTENT-LENGTH: 2
<
* Connection #1 to host 192.168.4.126 left intact
OKComplete!
$
The doorbell
takes the upload and returns a "200 OK" along with a "same origin" protection header and a few others (e.g. STS, if you were using SSL which we're not.) Note that we get back "OK and "Complete" with an immediate exit -- NO TIMEOUT, so the doorbell appears to have properly taken the upload.
However, there is no sound emitted
other than the click of the speaker unmuting (being powered on) and then turning back off!
It appears that the doorbell's closing of the connection (which you can't prohibit on the client end since you sent a complete frame with the length and then followed it with the actual data) causes the doorbell to immediately abort what was going to be speech output.
C'mon Amcrest, THAT needs to be fixed!