DoorBird: add transmit audio functionality

The DoorBird LAN-API allows for transmitting audio to it’s intercom through the /bha-api/audio-transmit.cgi endpoint (see page 18). This can be useful for sending short TTS messages and for instance letting people know you are not at home.

There is a separate AppDaemon app which seems to add this functionality. I havent tested it as I dont use AppDaemon (yet). I’d like to see this feature integrated in the default DoorBird integration.

I already tested the endpoint and functionality myself using curl and also with a Nodejs script. This works like a charm. Unfortunately my Python skills are to limited to come up with a pull request.

@oblogic7 or @bdraco , you seem to be listed as code owners for the DoorBird integration. Does this feature request sound viable?

For now I have created a work around which doesnt require AddDaemon which I’ll share here for anyone interested in adding this functionality.

All credits to @coobnoob for the script used. I only edited his/her AppDaemon script so it works as a standalone shell script. I’m in no way a Python coder so there are probably lots of improvements possible but the script works.

  1. Add the script below somewhere in your Home Assistant folder. I added it to a folder called custom_scripts.
  2. Add the following configuration to configuration.yaml and make sure you reference the name and location of the script correctly.
shell_command:
  doorbird_transmit_audio: python3 /config/custom_scripts/doorbird_transmit_audio.py {{ address }} {{ username }} {{ password }} {{ audio_file_path }}
  1. Create an automation with an action that looks similar to this, obviously using the correct IP address and credentials of your DoorBird.
action:
  - service: shell_command.doorbird_transmit_audio
    metadata: {}
    data:
      address: 192.168.0.134
      username: gxxxxxxxx2
      password: hxxxxxxxxk
      audio_file_path: /config/www/sounds/doorbird/not_at_home.mp3

The script

import subprocess
import sys
import requests
from requests.exceptions import RequestException
from time import sleep 
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.
  """
  while True:
    chunk = output_stream.read(chunk_size)
    if not chunk:
      break
    sleep(1) # We are rate limiting to chunk_size per second
    yield chunk

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()
2 Likes

Thanks for sharing! I will try to implement this next month. The intended use case is to send an audio message, if someone locks the door using the Doorbird keypad and a door or window is still left open.

I hadnt even thought about that use case but that’s a great one as well. Looking forward to the proper implementation.

Thanks

I was using gstreamer for this case.
But every Home Assistant update, I have to install gstreamer again

Hi,there news about this functionality?
It would be incredible, because I also use doubletake to recognize people, at this point if it were possible to launch a TTS on the intercom it would be possible to leave a personalized message for each person!

Hi, thanks for your post. Everything works for me, only mp3 is pronounced very quickly and as if not completely. Is there anything to consider
And as output I have the following
stdout: “”
stderr: (‘Connection aborted.’, BadStatusLine(‘\r\n’))
returncode: 0

Looking at the error it sounds like a bandwith issue. I have my DoorBird connected over PoE. My guess is yours is connected over WiFi and it cant handle this kind of traffic properly. Thats a guess though.

Also connected via poe. This is very strange
I have D2101KV when it’s important

Can you please help me? What else can I do, what can I checkCan you please help me? What else can I do, what can I check?
Can i have your mp3 to test?

Can you please explain how you do it with gstreamer? I installed gstreamer, but I don’t know how to proceed properly.