A short guide for setting up TV PiP notifications (with PiPup)

It sets the volume but still no sound, could it be another stream then 3? Or what does that argument stream do?

just try , it’s for setting soud stream (alarm , media , call ) different number different stream

I setup this a few days ago, What I do is to send an empty notification with 1 sec. It replaces the old one and closes.

I try this a few days ago, and now It will play on top of Netlix, but regardless of the sound of the stream being muted or not, or even if the stream has no sound track, It would mute Netflix forever, the only way is to go back to Home and reopen it.
I think it has to do with the way the android WebView handles the sound focus, but I couldn’t

I can’t get video feed to show up. The pop-up shows up but I just get a “webpage not available” background where the video should be. The url in the yaml below is the webrtc link from the go2rtc dashboard for the selected camera

action: rest_command.pipup_url_on_tv
data: 
  title: test
  message: test
  position: 0
  url: http://192.168.0.244:8123/api/hassio_ingress/bR3KwJm6Vd7M9VS9wpZerveaD4vytvIo/stream.html?src=camera.backyard_sub&mode=webrtc

the pipup_url_on_tv command is from @seanblanchfield tutorial.

pipup_url_on_tv:
  # Use with Webrtc camera as described here:
  # https://github.com/AlexxIT/WebRTC/wiki/Cast-or-share-camera-stream#html-page
  url: http://192.168.0.157:7979/notify
  content_type: 'application/json'
  verify_ssl: false
  method: 'post'
  timeout: 20
  payload: >
    {
      "duration": {{ duration | default(20) }},
      "position": {{ position | default(0) }},
      "title": "{{ title | default('') }}",
      "titleColor": "{{ titleColor | default('#50BFF2') }}",
      "titleSize": {{ titleSize | default(10) }},
      "message": "{{ message }}",
      "messageColor": "{{ messageColor | default('#fbf5f5') }}",
      "messageSize": {{ messageSize | default(14) }},
      "backgroundColor": "{{ backgroundColor | default('#0f0e0e') }}",
      "media": { 
        "web": {
          "uri": "{{ url }}", 
          "width": {{ width | default(640) }},
          "height": {{ height | default(480) }}
        }
      }
    }

I simply want to display a PIP video feed and don’t quite understand why it needs to first go through the webrtc create link service or how to do that part.

Does anyone have any advice for getting the camera stream to load even quicker? My automation is working but it’s taking 3-4 seconds to load my doorbell live feed each time. I’m already running the sub stream. rtsp://username:[email protected]:554/h264Preview_01_sub.

Also, I have redundancy with my camera and would like to only keep the lightest option. I’m running HA OS and I have a reolink doorbell. I currently have my doorbell live stream accessible through the Reolink integration, Frigate, and the generic camera I just created following Danny’s guide.. If I’m already using Frigate, do I still need the go2rtc add-on?

Here is my script currently.

  alias: Display Doorbell PIP Popup on TV
  mode: single
  variables:
    link_id: '{% for _ in range(40) %}{{ range(10)|random }}{% endfor %}'
  sequence:
  - service: webrtc.create_link
    data:
      link_id: '{{ link_id }}'
      entity: camera.doorbell
      open_limit: 1
      time_to_live: 60
  - service: rest_command.pipup_url_on_tv
    data:
      title: Door
      message: Someone is at the front door
      width: 640
      height: 480
      url: http://192.168.20.137:8123/webrtc/embed?url={{ link_id }}  #HA IP Address

1 Like

thanks for linking that, finally got this working. Mine has a delay too unforunately but it’s hit & miss. sometimes video shows up less than a second after triggered. Other times, I’ll see black screen with “play” logo loading and can take 3-4 seconds for the actual video feed.

I tried creating the generic camera entity through various rtsp links (rtsp link from camera ui, rtsp link from go2rtc and using camera.name entity generated from the unifi protect integration) and all act more or less than same. Currently using rtsp link from the unifi camera ui to create generic camera entity as detailed in tutortial you linked.

As the pop-up doesn’t work with video when there is DRM video being played, it was not so useful for me and could only show a screenshot on top. It also had random delays.

So, I moved to using Android Debug Bridge and send a command directly to the TV to open VLC with a specific video stream. That way you can open RTSP directly.

action: androidtv.adb_command
target:
  entity_id: media_player.livingroom_tv_adb
data:
  command: >-
    adb shell am start -n
    org.videolan.vlc/org.videolan.vlc.gui.video.VideoPlayerActivity
    rtsp://192.168.16.1:7447/AbCdEf123456

This is what works for my Unifi Protect doorbell. The IP is the local IP of my Protect controller. You can get the RTSP stream from the Unifi Protect interface. The links given shows RTSPS and port 7441 it should be RTSP and port 7447 for Unifi.

I have unifi protect G4 doorbell Pro and the TV PIP setup works fine for me. Not sure what DRM issue you’re running into. Does your VLC player workaround just launch VLC full screen?

The main issue I’m having is that the popup pauses what’s playing on screen. I’m currently troubleshooting that. Sending a “play” command to the android tv kind of works but the audio still cuts off for a few seconds before starting up again. If there’s a way to stop this bevahior? I want minimal interruption to what’s playing on screen.

My Sony Bravia’s with Google TV (Android TV 11) pauses the playing video if it’s non DRM content like PLEX or YouTube. You can try sending a video stream without audio in it.

But when you’re playing media on something like Disney+ or Netflix and the likes, it will give me a black pop-up if I send a video stream.

For the pop-up mode to work I eventually made an Automation that first sends the TV to the Home Screen and than render the Pop-up, that always worked.

My method opens fullscreen yes, independent of what is playing. So you don’t have those issues with no video in the pop-up. It also loads a lot faster, as VLC supports more.

Can you share your config for the UniFi doorbell. I have the pipup setup and go2rtc. I’m following a guide that calls for using wrbrtc but I see that webrtc is deprecated. I also setup a generic camera and I can see the stream from my doorbell. Just not sure how to apply it now so it shows on my android tv box.

I was having issues with stream load times and wanted to share everything I did to reduce them. I’m not a programmer, so there may still be room for improvement, but hopefully, this helps someone! I was able to reduce my load times from 6–8 seconds down to 2–3 seconds.

In the “Perform action ‘WebRTC Camera: Create Link’” action:

data:
  link_id: "{{ link_id }}"
  url: rtsp://username:password@NVR_IP_ADDRESS/h264Preview_03_sub
  open_limit: 1
  time_to_live: 60
action: webrtc.create_link
enabled: true

I used the RTSP stream from my Reolink cameras/NVR because I found that using the generic camera entity (e.g., camera.doorbell) in webrtc.create_link adds 1–3 seconds to the stream load time. It also seems to stutter and buffer more often then using the RTSP stream directly, sometimes not even loading untill 12-ish seconds after the popup starts.

Also, if you’re using Reolink cameras (which I am), use the H.264 sub-stream—it’s 1–2 seconds faster than the default stream.

In the “Perform action ‘rest_command.pipup_url_on_tv’” action:

data:
  title: Door
  message: Someone is at the front door
  width: 640
  height: 480
  url: >-
    http://home_assistant_IP:8123/webrtc/embed?url={{ link_id
    }}&mode=webrtc&media=video&transport=udp&ui=false # Flags go here after {{ link_id }}
action: rest_command.pipup_url_on_tv

Adding &mode=webrtc&media=video&transport=udp&ui=false at the end of the URL noticeably improved loading speeds for me.

  • &mode=webrtc → Forces the stream popup to use the RTC player instead of defaulting to MSE. Normally, when the camera stream starts, it auto-detects and switches modes, but forcing RTC from the start saves another 1-2 seconds.
  • &media=video → Ensures only the video loads, skipping the audio. This reduces load times by about 1-2 seconds and also prevents my Chromecast with Google TV from pausing whatever is playing. This feature is what got me started on this spiral of trying to optimize as much as possible. Originally I had to make an automation that resumes whatever was playing, but not anymore!
  • &transport=udp → Not sure if this actually helps or if it’s a placebo. ChatGPT suggested it might help, and maybe it does. I haven’t confirmed for sure.
  • &ui=false → Again, not entirely sure if this makes a significant difference, but since there’s no need for clickable UI elements in the RTC popup, it might slightly speed things up (less than a second).
  • You can use either of the above, it doesnt have to be all of them!
  • &poster=http://home_astnt_IP:8123/local/whatever pic you want.jpg → I use a poster, which is an image that is displayed in the player before the stream is fully loaded. This makes it feel like its loading faster than it does. My understanding is it can be any url, and I chose to use the snapshot of the camera that triggered the automation, so I get a shortlived view of the front walkway leading to my door.

Other optimizations I made:

On the Reolink NVR:

  • Set the DNS to static, using the router’s IP address as the DNS address.
  • In the stream settings, adjust the sub-stream of the camera you’re using:
    • Set I-frame interval to 1x.
    • Lower the bitrate as much as possible while maintaining acceptable quality.
  • Reboot the NVR after making these changes.

On my router:

  • Set QoS priorities to High for:
    • The NVR
    • The TV displaying the popup
    • The Home Assistant machine
  • Rebooted the router after applying these settings.

Doing all of the above made my popup go from a 6-10 second load, buffering and jittery stream to a solid 2-3 second load with no jitter or buffering AND NO PAUSING THE TV! (My wife is very happy about that). While combing the internet for answers I came across this forum post several times while troubleshooting, so I wanted to contribute my findings all in one place in case they help someone else trying to achieve the same thing!