I tried to solve this issue/problem. But unfortunately I couldn’t implement a satified solution because I’m not a python developer too.
But I could solve issue.
First of all I had to use the Advanced SSH & Web Terminal addon to install some missing python modules (I saw these errors when I executed the python script in the terminal…):
- Error:
File "/config/custom_scripts/doorbird_transmit_audio.py", line 3, in <module>
import requests
ModuleNotFoundError: No module named 'requests'
Solution:
python3 -m pip install requests
- Error:
[Errno 2] No such file or directory: 'ffmpeg'#
Solution:
apk add ffmpeg
Then the script was executed and the audio was transfered to the doorbird but still with the error:
stdout: “”
stderr: (‘Connection aborted.’, BadStatusLine(‘\r\n’))
returncode: 0
But unfortunately the audio was terrible to listen on the doorbird.
Then I adapted the Python script of @Phuturist to this (like in Doorbird play audio clip through speaker - #7 by Thorbeen with “clipping a little”):
import subprocess
import sys
import requests
from requests.exceptions import RequestException
from time import sleep, time
from io import BytesIO
# Credits for this script go to Kristian (coobnoob). The base of this script is a copy from https://github.com/coobnoob/ha-appdaemon-doorbird-audio/tree/main
# usage examples
# python3 /config/custom_scripts/doorbird_transmit_audio.py 192.168.0.134 username password /config/www/sounds/doorbird/not_at_home.mp3
# parameters
base_url = "http://%s/bha-api" % (sys.argv[1])
auth = (sys.argv[2], sys.argv[3])
def _generate_audio_chunks(output_stream, chunk_size=8*1024):
"""
Generator function to yield chunks of audio data from a file.
Doorbird is rate limited to 8K per second
Args:
output_stream: Stream of audio
chunk_size (int): Size of each chunk in bytes.
Yields:
bytes: Chunks of audio data.
"""
next_chunk_time = time()
while True:
start_time = time()
chunk = output_stream.read(chunk_size)
if not chunk:
break
#sleep(1) # We are rate limiting to chunk_size per second
yield chunk
elapsed_time = time() - start_time
next_chunk_time += 0.5
sleep_time = max(0, next_chunk_time - time())
#self._log_timing(self.CHUNK_SIZE, elapsed_time, sleep_time)
sleep(sleep_time)
def send_audio(audio_file_path):
"""
Send audio to Doorbird
Args:
audio_file_path (str): Path to the audio file to be transmitted.
Raises:
Exception
"""
try:
response = requests.get(f"{base_url}/getsession.cgi", auth=auth)
response.raise_for_status()
# Check if the request was successful (HTTP status code 200)
if response.status_code == 200:
data = response.json()
session_id = data["BHA"]["SESSIONID"]
else:
raise Exception(f"Failed to obtain session ID. Status code: {response.status_code}")
# Prepare headers
headers = {
"Content-Type": "audio/basic",
"Connection": "Keep-Alive",
"Cache-Control": "no-cache"
}
# Command to convert the file to an a mono, 8000Khz mu-law wav
command = [
"ffmpeg",
"-y",
"-i", audio_file_path,
"-ac", "1",
"-ar", "8000",
"-f", "wav",
"-codec:a", "pcm_mulaw",
"-"
]
# Convert the file to an in-memory, mono, 8000Khz mu-law wav
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
result.check_returncode()
# Make the POST request with the audio data generator to chunk the file
with requests.post(
f"{base_url}/audio-transmit.cgi?sessionid={session_id}",
headers=headers,
data=_generate_audio_chunks(BytesIO(result.stdout), chunk_size=8*1024),
auth=auth,
stream=True
) as response:
if response.status_code != 200:
sys.stderr.write("Failed to transmit audio. \n")
response.raise_for_status()
sys.exit()
except requests.exceptions.RequestException as e:
sys.stderr.write(str(e))
sys.exit()
# Make the request
try:
send_audio(sys.argv[4])
except Exception as e:
sys.stderr.write(str(e))
sys.exit()
the important part is the _generate_audio_chunks method with the new sleep time. BUT even then the audio file is not played clear and satified on the doorbird. the “still clipping a little” from the mentioned link is a showstopper for me… 
Maybe there is someone who can solve this issue finally please? That would be great 