Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stream not working on any cameras #151

Open
CarterBrehm opened this issue Jan 18, 2020 · 59 comments
Open

Stream not working on any cameras #151

CarterBrehm opened this issue Jan 18, 2020 · 59 comments
Assignees
Labels
enhancement New feature or request

Comments

@CarterBrehm
Copy link

I have v0.6.8 of this integration installed through HACS in a virtualenv and while all of the sensors and snapshots work fine when I use the lovelace card the stream shows up but doesn't actually move at all, while the log reports errors:

2020-01-18 13:21:01 ERROR (stream_worker) [homeassistant.components.stream.worker] Error demuxing stream: No dts in packet
2020-01-18 13:21:16 ERROR (stream_worker) [homeassistant.components.stream.worker] Error demuxing stream: No dts in packet
2020-01-18 13:22:49 WARNING (MainThread) [asyncio] socket.send() raised exception.
2020-01-18 13:22:49 WARNING (MainThread) [asyncio] socket.send() raised exception.
2020-01-18 13:22:49 WARNING (MainThread) [asyncio] socket.send() raised exception.
2020-01-18 13:22:49 WARNING (MainThread) [asyncio] socket.send() raised exception.
2020-01-18 13:22:49 WARNING (MainThread) [asyncio] socket.send() raised exception.
2020-01-18 13:22:49 WARNING (MainThread) [asyncio] socket.send() raised exception.
2020-01-18 13:22:49 WARNING (MainThread) [asyncio] socket.send() raised exception.

Occasionally, I also get a 2020-01-18 13:28:00 WARNING (ArloEventStream) [pyaarlo] general exception must be str, not NoneType which doesn't seem to be related to any action I take.
I've followed the streaming instructions in the bottom of the readme, here are the relevant parts of my config:

stream:

camera:
  - platform: aarlo
    ffmpeg_arguments: '-pred 1 -q:v 2'

aarlo:
  username: !secret arlo_email
  password: !secret arlo_password
  packet_dump: False
  db_motion_time: 30
  db_ding_time: 10
  recent_time: 10
  last_format: '%-I:%M %p'
  no_media_upload: True
  mode_api: auto
  refresh_devices_every: 0
  http_connections: 5
  http_max_size: 10
  host: https://my.arlo.com

Let me know if I need to raise my logging level or anything.

@twrecked
Copy link
Owner

What kind of cameras are you using?

@twrecked twrecked self-assigned this Jan 20, 2020
@CarterBrehm
Copy link
Author

I'm using a Video Doorbell, two Q's, and I think I just have regular Arlo Pro cameras for the outside. 6 cameras in total. I've done some more experimenting and it seems like sometimes it will show the last recorded motion event, but I haven't gotten it to stream yet.

@twrecked
Copy link
Owner

twrecked commented Feb 1, 2020

I think this needs fixing with the stream component. I'll see if somebody is willing to lend me an Arlo Q camera to test.

@ghost
Copy link

ghost commented Feb 17, 2020

Hi!

Just adding that I've similars issues with Arlo Q and livestream:

2020-02-17 20:42:51 INFO (MainThread) [homeassistant.components.stream] Started stream: rtsps://vzwow165-z1-prod.ar.arlo.com:443/vzmodulelive/...?egressToken=token&userAgent=iOS&cameraId=cameraid
2020-02-17 20:42:54 INFO (SyncWorker_12) [homeassistant.components.netgear.device_tracker] Scanning
2020-02-17 20:42:54 INFO (SyncWorker_12) [pynetgear] Get attached devices 2
2020-02-17 20:42:57 ERROR (stream_worker) [homeassistant.components.stream.worker] Error demuxing stream: No dts in packet
2020-02-17 20:42:57 INFO (MainThread) [homeassistant.components.stream] Stopped stream: rtsps://vzwow165-z1-prod.ar.arlo.com:443/vzmodulelive/...?egressToken=token&userAgent=iOS&cameraId=cameraid
2020-02-17 20:42:57 ERROR (MainThread) [aiohttp.server] Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_protocol.py", line 418, in start
    resp = await task
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_app.py", line 458, in _handle
    resp = await handler(request)
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_middlewares.py", line 119, in impl
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/real_ip.py", line 39, in real_ip_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 72, in ban_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 135, in auth_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 123, in handle
    result = await result
  File "/usr/src/homeassistant/homeassistant/components/stream/core.py", line 181, in get
    return await self.handle(request, stream, sequence)
  File "/usr/src/homeassistant/homeassistant/components/stream/hls.py", line 36, in handle
    body=renderer.render(track, utcnow()).encode("utf-8"), headers=headers
  File "/usr/src/homeassistant/homeassistant/components/stream/hls.py", line 95, in render
    + self.render_playlist(track, start_time)
  File "/usr/src/homeassistant/homeassistant/components/stream/hls.py", line 67, in render_preamble
    return ["#EXT-X-VERSION:3", f"#EXT-X-TARGETDURATION:{track.target_duration}"]
  File "/usr/src/homeassistant/homeassistant/components/stream/core.py", line 83, in target_duration
    return round(sum(durations) // len(self._segments)) or 1
ZeroDivisionError: integer division or modulo by zero

@twrecked
Copy link
Owner

Is anybody comfortable with debugging from Chrome? I want to see if the command to start streaming is different for Q cameras. Basically:

The debug window will be filling up. Click on the Network tag.

  • choose a camera
  • start a livestream

Look for a packet in the Name window called startStream and select it. I'm interested in the Headers and Preview tabs of the packet.

In the Headers tag scroll down to the Request Payload, expand it as much as possible and paste it anonymized here.

In the Preview tag expand the response as much as possible and paste it anonymized here.

For my cameras they look something like this:

to: "4XXXXXXXXXX8"
from: "XXXXXXXXXX_web"
resource: "cameras/5XXXXXXXXXX"
action: "set"
responseUrl: ""
publishResponse: true
transId: "web!7ff03760.a1db6!1582143108843"
properties: {activityState: "startUserStream", cameraId: "5XXXXXXX"}
activityState: "startUserStream"
cameraId: "5XXXXXXXXXX"

and

data: {,…}
url: "rtmps://vzwow92-z1-prod.ar.arlo.com:80/vzmodulelive?egressToken=306d4a2XXXXXXXXXXXXXXXX&userAgent=web&cameraId=XXXXXXXXX_1582143108927"
success: true

@ghost
Copy link

ghost commented Feb 19, 2020

Here's for a Arlo Q camera:

to: "4XXXXXXXXXXX1"
from: "XXXX-XXX-XXXXXXXX_web"
resource: "cameras/4XXXXXXXXXXX1"
action: "set"
responseUrl: ""
publishResponse: true
transId: "web!ecb1f6aa.7fea5!1582144947531"
properties: {activityState: "startUserStream", cameraId: "4XXXXXXXXXXX1"}
activityState: "startUserStream"
cameraId: "4XXXXXXXXXXX1"
data: {,…}
url: "rtmps://vzwow52-z1-prod.ar.arlo.com:80/vzmodulelive?egressToken=mytoken&userAgent=web&cameraId=mycameraid__1582144961554"
success: true

Seems like there's a little difference in the url, vzwow92 for you and vzwow52 for me.

@twrecked
Copy link
Owner

Thanks for the quick reply. Which OS was that from?

And yes, there was no significant difference at all. I was hoping there was something then I could have added it to the code for Q cameras and see if it fixed the problem.

Another option is a different user agent. This is a long shot but might work with the Arlo Q cameras. Add this to your config and restart HA.

aarlo:
  user_agent: linux

@ghost
Copy link

ghost commented Feb 20, 2020

The previous info was from macOS 10.15.3 (Chrome 80.0.3987.87).

With your line, I ain't got the error, but the stream doesn't work either.

2020-02-20 08:43:58 INFO (MainThread) [homeassistant.components.stream] Started stream: rtmps://vzwow78-z1-prod.ar.arlo.com:80/vzmodulelive?egressToken=mytoken&userAgent=web&cameraId=mycameraid_1582184633984

@twrecked
Copy link
Owner

Now it gets fun - we need to check if the stream is actually readable by the ffmpeg executable inside home-assistant. This gets complicated and I'm hoping somebody out there will have some coding/console/home-assistant-messing-about experience and can try this with an ArloQ camera. What we need to do is:

  • modify the Aarlo code to start a stream but stop it being passed back into the stream component
  • locate the newly created stream, open an ffmpeg connection to it and capture that output

Luckily we can jerry-rig (jury-rig?) most of this.

This patch will request Arlo start the stream but stop the URL being passed back to the stream component. Apply it directly to the Aarlo custom component under your home assistant configuration directory - It's one line so probably easiest to apply it manually.

diff --git a/custom_components/aarlo/pyaarlo/camera.py b/custom_components/aarlo/pyaarlo/camera.py
index 591f331..d8c123e 100644
--- a/custom_components/aarlo/pyaarlo/camera.py
+++ b/custom_components/aarlo/pyaarlo/camera.py
@@ -475,7 +475,7 @@ class ArloCamera(ArloChildDevice):
             return None
         url = reply['url'].replace("rtsp://", "rtsps://")
         self._arlo.debug('url={}'.format(url))
-        return url
+        return None
 
     def get_video(self):
         video = self.last_video

Make sure debug is turned on. Set logger: in configuration.yaml to this:

logger:
  default: info
  logs:
    pyaarlo: debug

Restart your home-assistant.

Cut and paste the following shell script into your home-assistant configuration directory, call it stream.

#!/bin/bash
#

URL=$(grep url= home-assistant.log | tail -1 | cut -f 2- -d =)
if [[ -z "${URL}" ]]; then
	echo "no url"
	exit 1
fi
echo $URL

mkdir s 2>/dev/null
ffmpeg -i ${URL} \
	-fflags flush_packets -max_delay 2 -flags -global_header \
	-hls_time 2 -hls_list_size 3 -vcodec copy -y s/video.m3u8

Enter your home-assistant environment and make stream executable. The first time you run it there won't be a stream so it will do nothing. I'm using a docker so my commands goes like this:

$ docker exec -it home-assistant bash
bash-5.0# chmod +x stream
bash-5.0# ./stream
no url

For a virtualenv install it's probably sufficient to source the appropriate activate file and change to your config directory. Now start a live stream, wait a few seconds and run the stream command again. This time it should try and connect to the Arlo servers and start generating hls output. For my non-ArloQ cameras it looks like this:

bash-5.0# ./stream 
rtsps://vzwow117-z1-prod.ar.arlo.com:443/vzmodulelive/XXXXXXXXXX_1582255723060?egressToken=fcf7187b_54b0_4f3a_9ea1_0a80943e00f0&userAgent=iOS&cameraId=XXXXXXXXX_F23_1582255723060
ffmpeg -fflags nobuffer -rtsp_transport tcp -i rtsps://vzwow117-z1-prod.ar.arlo.com:443/vzmodulelive/XXXXXXXXXX_1582255723060?egressToken=fcf7187b_54b0_4f3a_9ea1_0a80943e00f0&userAgent=iOS&cameraId=XXXXXXXXXX_1582255723060 -vsync 0 -copyts -vcodec copy -movflags frag_keyframe+empty_moov -an -hls_flags delete_segments+append_list -f segment -segment_list_flags live -segment_time 1 -segment_list_size 3 -segment_format mpegts -segment_list s/index.m3u8 -segment_list_type m3u8 -segment_list_entry_prefix /stream/ s/%d.ts
ffmpeg version 4.1.4 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.3.0 (Alpine 8.3.0)
  configuration: --prefix=/usr --enable-avresample --enable-avfilter --enable-gnutls --enable-gpl --enable-libass --enable-libmp3lame --enable-libvorbis --enable-libvpx --enable-libxvid --enable-libx264 --enable-libx265 --enable-libtheora --enable-libv4l2 --enable-postproc --enable-pic --enable-pthreads --enable-shared --enable-libxcb --disable-stripping --disable-static --disable-librtmp --enable-vaapi --enable-vdpau --enable-libopus --disable-debug
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Input #0, rtsp, from 'rtsps://vzwow117-z1-prod.ar.arlo.com:443/vzmodulelive/XXXXXXX3_1582255723060?egressToken=fcf7187b_54b0_4f3a_9ea1_0a80943e00f0&userAgent=iOS&cameraId=XXXXXXXXXX_1582255723060':
  Metadata:
    title           : XXXXXXXXXX_1582255723060
  Duration: N/A, start: 0.320000, bitrate: N/A
    Stream #0:0: Audio: aac (LC), 16000 Hz, mono, fltp
    Stream #0:1: Video: h264 (High), yuvj420p(pc, bt709, progressive), 1920x1072, 15 fps, 15 tbr, 90k tbn, 30 tbc
Stream mapping:
  Stream #0:1 -> #0:0 (copy)
  Stream #0:0 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
[hls @ 0x55de5a79ed00] Opening 's/video0.ts' for writing
Output #0, hls, to 's/video.m3u8':
  Metadata:
    title           : XXXXXXXXXX_1582255723060
    encoder         : Lavf58.20.100
    Stream #0:0: Video: h264 (High), yuvj420p(pc, bt709, progressive), 1920x1072, q=2-31, 15 fps, 15 tbr, 90k tbn, 15 tbc
    Stream #0:1: Audio: aac (LC), 16000 Hz, mono, fltp, 69 kb/s
    Metadata:
      encoder         : Lavc58.35.100 aac
[hls @ 0x55de5a79ed00] Non-monotonous DTS in output stream 0:0; previous: 50970, current: 21060; changing to 50971. This may result in incorrect timestamps in the output file.
[hls @ 0x55de5a79ed00] Non-monotonous DTS in output stream 0:0; previous: 50971, current: 27000; changing to 50972. This may result in incorrect timestamps in the output file.
[hls @ 0x55de5a79ed00] Non-monotonous DTS in output stream 0:0; previous: 50972, current: 33030; changing to 50973. This may result in incorrect timestamps in the output file.
[hls @ 0x55de5a79ed00] Non-monotonous DTS in output stream 0:0; previous: 50973, current: 38970; changing to 50974. This may result in incorrect timestamps in the output file.
[hls @ 0x55de5a79ed00] Non-monotonous DTS in output stream 0:0; previous: 50974, current: 45000; changing to 50975. This may result in incorrect timestamps in the output file.
[hls @ 0x55de5a79ed00] Non-monotonous DTS in output stream 0:0; previous: 50975, current: 50940; changing to 50976. This may result in incorrect timestamps in the output file.
[hls @ 0x55de5a79ed00] Opening 's/video1.ts' for writing
[hls @ 0x55de5a79ed00] Cannot use rename on non file protocol, this may lead to races and temporary partial files
[hls @ 0x55de5a79ed00] Opening 's/video2.ts' for writingrate=N/A speed=1.97x    
[hls @ 0x55de5a79ed00] Opening 's/video3.ts' for writingrate=N/A speed=1.48x    
[hls @ 0x55de5a79ed00] Opening 's/video4.ts' for writingrate=N/A speed=1.43x    
frame=  145 fps= 19 q=-1.0 Lsize=N/A time=00:00:10.28 bitrate=N/A speed=1.35x    
video:1035kB audio:67kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
[aac @ 0x55de5a77fc00] Qavg: 65523.383
Exiting normally, received signal 2.

@twrecked
Copy link
Owner

This diff might be easier to try. It will turn on debugging to the Python av component. You have to make this change inside the homeassistant code.

diff --git a/homeassistant/components/stream/__init__.py b/homeassistant/components/stream/__init__.py
index d88f90a83..308dc5b77 100644
--- a/homeassistant/components/stream/__init__.py
+++ b/homeassistant/components/stream/__init__.py
@@ -37,7 +37,9 @@ SERVICE_RECORD_SCHEMA = STREAM_SERVICE_SCHEMA.extend(
     }
 )
 # Set log level to error for libav
-logging.getLogger("libav").setLevel(logging.ERROR)
+logging.getLogger("libav").setLevel(logging.DEBUG)
+logging.getLogger().setLevel(5)
+
 
 
 @bind_hass

Restart homeassistant, start a stream and you'll see something like this in the logging which might help us work out what is going wrong:

2020-02-21 09:55:38 WARNING (stream_worker) [libav.mpegts] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
2020-02-21 09:55:38 WARNING (stream_worker) [libav.mpegts] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
2020-02-21 09:55:40 INFO (stream_worker) [libav.aac] Qavg: 65536.000
2020-02-21 09:55:40 WARNING (stream_worker) [libav.aac] 2 frames left in the queue on closing
2020-02-21 09:55:40 WARNING (stream_worker) [libav.mpegts] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
2020-02-21 09:55:40 WARNING (stream_worker) [libav.mpegts] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
2020-02-21 09:55:42 INFO (stream_worker) [libav.aac] Qavg: 65536.000

@cschleiden
Copy link

Only have a hassio setup, but taking the stream url and trying on my host with:

ffmpeg -version
ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers
built with Apple clang version 11.0.0 (clang-1100.0.33.16)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.2.2 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags='-I/Library/Java/JavaVirtualMachines/adoptopenjdk-13.0.1.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/adoptopenjdk-13.0.1.jdk/Contents/Home/include/darwin -fno-stack-check' --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libmp3lame --enable-libopus --enable-librubberband --enable-libsnappy --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --disable-libjack --disable-indev=jack
libavutil      56. 31.100 / 56. 31.100
libavcodec     58. 54.100 / 58. 54.100
libavformat    58. 29.100 / 58. 29.100
libavdevice    58.  8.100 / 58.  8.100
libavfilter     7. 57.100 /  7. 57.100
libavresample   4.  0.  0 /  4.  0.  0
libswscale      5.  5.100 /  5.  5.100
libswresample   3.  5.100 /  3.  5.100
libpostproc    55.  5.100 / 55.  5.100

ffmpeg -v verbose -fflags flush_packets -max_delay 2 -flags -global_header -hls_time 2 -hls_list_size 3 -vcodec copy -y s/video.m3u8 -i "rtmps://vzwow388-z2-prod.ar.arlo.com:80/vzmodulelive?egressToken=XXXXXX&userAgent=web&cameraId=XXXX"

Parsing...
Parsed protocol: 4
Parsed host    : vzwow388-z2-prod.ar.arlo.com
Parsed app     : vzmodulelive?egressToken=XXXXX&userAgent=web&cameraId=XXXXXX
HandShake: Type Answer   : 03
HandShake: Server Uptime : 96850052
HandShake: FMS Version   : 3.0.1.1
HandShake: Handshaking finished....
RTMP_Connect1, handshaked
Invoking connect
HandleServerBW: server BW = 2500000
HandleClientBW: client BW = 2500000 2
HandleCtrl, received ctrl. type: 0, len: 6
HandleCtrl, Stream Begin 0
HandleChangeChunkSize, received: chunk size change to 512
RTMP_ClientPacket, received: invoke 336 bytes
(object begin)
Property: <Name:           no-name., STRING:	_error>
Property: <Name:           no-name., NUMBER:	1.00>
Property: NULL
Property: <Name:           no-name., OBJECT>
(object begin)
Property: <Name:              level, STRING:	error>
Property: <Name:               code, STRING:	NetConnection.Connect.Rejected>
Property: <Name:        description, STRING:	Connection failed: Application rejected connection.>
Property: <Name:        application, STRING:	invalid request>
Property: <Name:                 ex, OBJECT>
(object begin)
Property: <Name:           redirect, STRING:	 Not valid request>
Property: <Name:               code, NUMBER:	302.00>
(object end)
Property: <Name:           clientid, NUMBER:	2037XXXXXX.00>
Property: <Name:        secureToken, STRING:	XXXXXXXXXXXXXX>
(object end)
(object end)
HandleInvoke, server invoking <_error>
rtmp server sent error
RTMP_ClientPacket, received: invoke 18 bytes
(object begin)
Property: <Name:           no-name., STRING:	close>
Property: <Name:           no-name., NUMBER:	0.00>
Property: NULL
(object end)
HandleInvoke, server invoking <close>
rtmp server requested close

@cschleiden
Copy link

This is interesting: tchellomello/python-arlo#8

So when I make a request to https://my.arlo.com/hmsweb/users/devices/startStream with that Mozilla/5.0 (iPhone; CPU iPhone OS 11_1_2 like Mac OS X) AppleWebKit/604.3.5 (KHTML, like Gecko) Mobile/15B202 NETGEAR/v1 (iOS Vuezone) user agent, I do get a rtsp:// url back.

Changing the protocol then to rtsps:// allows me to capture the stream via ffmpeg -v verbose -re -i "rtsps://vzwow233-z2-prod.ar.arlo.com:443/vzmodulelive/xxx?egressToken=xxx&userAgent=iOS&cameraId=xxxx" -acodec copy -vcodec copy ./test.mp4 which I can then successfully play.

@twrecked
Copy link
Owner

I already fix up the rtsp:// to rtsps://, it's one of the many Arlo quirks!

And in the previous post you're getting a rtmps: stream, do you have a user_agent configured?

@cschleiden
Copy link

cschleiden commented Feb 23, 2020

When I used the linux user agent, I got an rtmps: url that I wasn't able to stream. Turns out with the default settings you have I already got that rtsp:// stream, so I removed the user_agent config again.

In the end, the problem with my Q cameras came down to this:
https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/stream/worker.py#L77

Changing that to not throw an error and to just ignore the packet gets me a stream in the UI. Also found some earlier discussion about this here: home-assistant/core#22840 (comment)

Haven't contributed to HA so far so don't have a local setup yet but will see if we can get that change into there.

@twrecked
Copy link
Owner

That's great you got it going. I was leaning towards the problem being in the stream component but I like to get as much information as possible before raising the issue.

And many thanks for your work here.

@twrecked
Copy link
Owner

Does this patch look something similar to how you get it working? I just ignore the first 10 dts errors.

--- /usr/src/homeassistant.orig/homeassistant/components/stream/worker.py
+++ /usr/src/homeassistant/homeassistant/components/stream/worker.py
@@ -66,6 +66,8 @@
     first_pts = 0
     # The decoder timestamp of the latest packet we processed
     last_dts = None
+    # Allow some no dts packets in
+    no_dts = 0
 
     while not quit_event.is_set():
         try:
@@ -73,8 +75,13 @@
             if packet.dts is None:
                 if first_packet:
                     continue
+                ++no_dts
+                if no_dts < 10:
+                    continue
                 # If we get a "flushing" packet, the stream is done
-                raise StopIteration("No dts in packet")
+                raise StopIteration("No dts in packet too often")
+            else:
+                no_dts = 0
         except (av.AVError, StopIteration) as ex:
             # End of stream, clear listeners and stop thread
             for fmt, _ in outputs.items():

@cschleiden
Copy link

For the quick test I didn't have a counter, but this seems fine!

@blair287
Copy link

blair287 commented Mar 5, 2020

Does the latest update fix the arlo q live stream if it does. ive updated and its doing the same thing no live stream.

@twrecked
Copy link
Owner

twrecked commented Mar 5, 2020

I can't fix it from inside the Aarlo component you need to patch the stream: component and try.

You can copy the patch in the previous+2 post into a file called /config/aarlo.patch and reboot twice - the first time to patch stream, the second to use the newly patched stream - and see if that works.

@blair287
Copy link

blair287 commented Mar 5, 2020

Do i need to create that file? and then just copy the patch from the above comment from you into that file.

@twrecked
Copy link
Owner

twrecked commented Mar 5, 2020

For now, yes. I need to know where the file is and the config directory is the easiest to locate.

I'll work on a nicer way of doing this.

@blair287
Copy link

blair287 commented Mar 5, 2020

For now, yes. I need to know where the file is and the config directory is the easiest to locate.

I'll work on a nicer way of doing this.

if it goes wrong anyway to revert the stream componment back to how it was? will a snap shot work or?

@twrecked
Copy link
Owner

twrecked commented Mar 5, 2020

This is a reverse of the diff, copy this to /config/aarlo.patch and that should fix it. Are you using docker or virtualenv?

--- /usr/src/homeassistant/homeassistant/components/stream/worker.py
+++ /usr/src/homeassistant.orig/homeassistant/components/stream/worker.py
@@ -66,8 +66,6 @@
     first_pts = 0
     # The decoder timestamp of the latest packet we processed
     last_dts = None
-    # Allow some no dts packets in
-    no_dts = 0
 
     while not quit_event.is_set():
         try:
@@ -75,13 +73,8 @@
             if packet.dts is None:
                 if first_packet:
                     continue
-                ++no_dts
-                if no_dts < 10:
-                    continue
                 # If we get a "flushing" packet, the stream is done
+                raise StopIteration("No dts in packet")
-                raise StopIteration("No dts in packet too often")
-            else:
-                no_dts = 0
         except (av.AVError, StopIteration) as ex:
             # End of stream, clear listeners and stop thread
             for fmt, _ in outputs.items():

@blair287
Copy link

blair287 commented Mar 5, 2020

im using docker on ubuntu 18.04

ive not tried it yet i just wanted to know how to get back to original if it didnt work. does this patch fix it to allow live streaming for a q on the custom aarlo card i haven't miss read have i?

do you think this will be easy to fix in the future or will this patch be required anyway?

@twrecked
Copy link
Owner

twrecked commented Mar 5, 2020

With a docker you can just throw the docker instance away and start again.

The patch should allow Arlo Q cameras to stream. I don't have one so I'm relying on people with Q cameras to let me know if it works.

It is a simple fix but looking at the comments in the stream threads in home-assistant.io it's been known about for a while.

@mk-mrshll
Copy link

mk-mrshll commented Mar 8, 2020

@twrecked I can give this a shot. Are you saying to literally copy that diff below (with the pluses and minuses) into that location?

--- /usr/src/homeassistant.orig/homeassistant/components/stream/worker.py
+++ /usr/src/homeassistant/homeassistant/components/stream/worker.py
@@ -66,6 +66,8 @@
     first_pts = 0
     # The decoder timestamp of the latest packet we processed
     last_dts = None
+    # Allow some no dts packets in
+    no_dts = 0
 
     while not quit_event.is_set():
         try:
@@ -73,8 +75,13 @@
             if packet.dts is None:
                 if first_packet:
                     continue
+                ++no_dts
+                if no_dts < 10:
+                    continue
                 # If we get a "flushing" packet, the stream is done
-                raise StopIteration("No dts in packet")
+                raise StopIteration("No dts in packet too often")
+            else:
+                no_dts = 0
         except (av.AVError, StopIteration) as ex:
             # End of stream, clear listeners and stop thread
             for fmt, _ in outputs.items():

@mk-mrshll
Copy link

mk-mrshll commented Mar 8, 2020

Okay, so I gave it a go, and the results don't look good.

On first restart, I get the log to show up (It seems it logs this as an error even though it's really an info log):

Log Details (ERROR)
Sun Mar 08 2020 12:25:41 GMT-0500 (Central Daylight Time)
/usr/bin/patch -p0 -N < '/config/aarlo.patch'

After second restart, trying to stream from the aarlo lovelace card makes this show up in the logs (same stuff from before):

Log Details (ERROR)
Sun Mar 08 2020 12:32:15 GMT-0500 (Central Daylight Time)
Error demuxing stream: No dts in packet
Log Details (ERROR)
Sun Mar 08 2020 12:32:15 GMT-0500 (Central Daylight Time)
Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_protocol.py", line 418, in start
    resp = await task
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_app.py", line 458, in _handle
    resp = await handler(request)
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_middlewares.py", line 119, in impl
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/real_ip.py", line 39, in real_ip_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 72, in ban_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 135, in auth_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 123, in handle
    result = await result
  File "/usr/src/homeassistant/homeassistant/components/stream/core.py", line 181, in get
    return await self.handle(request, stream, sequence)
  File "/usr/src/homeassistant/homeassistant/components/stream/hls.py", line 36, in handle
    body=renderer.render(track, utcnow()).encode("utf-8"), headers=headers
  File "/usr/src/homeassistant/homeassistant/components/stream/hls.py", line 95, in render
    + self.render_playlist(track, start_time)
  File "/usr/src/homeassistant/homeassistant/components/stream/hls.py", line 67, in render_preamble
    return ["#EXT-X-VERSION:3", f"#EXT-X-TARGETDURATION:{track.target_duration}"]
  File "/usr/src/homeassistant/homeassistant/components/stream/core.py", line 83, in target_duration
    return round(sum(durations) // len(self._segments)) or 1
ZeroDivisionError: integer division or modulo by zero

I want to say this is probably because the patching code in the component is not finding the right place to apply the patch. I'm running homeassistant through docker on an Ubuntu VM, and I don't seem to have a /usr/src/homeassistant folder. In order to apply this patch, do I need to be running homeassistant from source code?

@twrecked
Copy link
Owner

twrecked commented Mar 9, 2020

The stream component needs to be fixed to handle this error better, the patch is a huge kludge.

But, it should work on a docker, you'll have problems with virtualenv but docker has a fixed source location. Did you check from inside the docker?

$ docker exec -it your-docker-instance-name bash
# cd /usr/src
# ls

I'll work on generating a PR for the stream component. But it'll take me a couple of days to do it.

@twrecked twrecked added enhancement New feature or request and removed bug Something isn't working labels May 10, 2020
@blair287
Copy link

Almost... I have to generate a patch for the detected I/O issue so I'm using that as a test. But if anybody wants to generate a PR, be my guest.

I would love to help but have no idea where to start :(

@dermotduffy
Copy link
Contributor

I have prepared this change:

dermotduffy/hass-core@73b0d2f

Skipping a single packet without dts is sufficient for my Arlo Qs to stream correctly (and somehow psychologically skipping 1 bad packet feels less kludgey than skipping a const 10!).

@twrecked you appear to be working on this issue, and you know this area much better than I. Would you like me to submit this as a PR, or should I hold off (e.g. if you have a better fix in mind)?

@twrecked
Copy link
Owner

@dermotduffy If you could submit it that would be great. I don't have any of the cameras streaming doesn't work on so didn't have a way of testing before I submitted it.

hunterjm pushed a commit to home-assistant/core that referenced this issue Jul 13, 2020
* Allow 1 packet without dts. See twrecked/hass-aarlo#151 .

* Reset boolean once a packet with dts is found.

* Fix no-else-continue lint error.
@twrecked
Copy link
Owner

It now looks like Arlo has changed their streaming. I connected to their website today and the cameras are streaming in HLS directly from Arlo. This probably means we can bypass the stream: component and stream directly from Arlo. Obviously I need to figure out how.

Can somebody with Ultra cameras confirm this? You will need to open a debug console (CTRL + SHIFT + T in Chrome) and start a stream. Look for m4s packets.

@twrecked
Copy link
Owner

I have a fix but it needs trying. As I mentioned above, it looks like Arlo is moving away from flash and is now using mpeg-dash to stream from their cameras. This means we can stream directly from Arlo instead of via Home Assistant. I modified the lovelace card to make this work. To try this, you need to do the following:

  • change the user agent to linux in your home assistant configuration and restart
aarlo:
  user_agent: linux
  • upgrade lovelace-aarlo to the latest, v0.1.2
  • add the following to each lovelace camera entity (I'm hoping I can remove this step eventually)
play_direct: true

Now try streaming. One bonus, the audio now works.

To undo, just remove the play_direct and user_agent changes. The lovelace card is backward compatible.

If somebody with ultra cameras could try this it would be great.

@cschleiden
Copy link

Nice, works great with my Arlo Q cameras!

@dermotduffy
Copy link
Contributor

Hurray -- it's a proper fix for streaming from Q cameras that doesn't rely on arbitrarily skipping packets without dts...

Confirmed streaming working on Arlo Qs and Pro 2s.

@twrecked
Copy link
Owner

@dermotduffy Yeah, I just happened to notice the web interface was using mpeg-dash the other day.

The problem is, the user_agent breaks the stream: component which doesn't recognize the mpd type so no saving streams - you can try this by removing the play_direct from the Lovelace card. So we still might still need your PR.

@ssilence5
Copy link

@twrecked, this doesn't seem to have an affect on the Arlo Pro 3 cameras. I can live stream just like I could before without audio. And anything that is recorded I can playback but will get no video, but I will get audio.

@twrecked
Copy link
Owner

@ssilence5
It doesn't affect the playback of library files, they still come in in an mpg file. Do the library files play on web interface?

But you should get audio on the live stream. Can you check that on the web interface? We may need to add some parameters to the setup.

@ssilence5
Copy link

@twrecked
You caught me there. Let me walk through what happens on the web portal.

Playback doesn't work at all on the Arlo portal for most browsers. I have linked this to the fact that the format is in HEVC (Arlo Pro 3 is 2K). I did get it to work in either Edge or IE, can't remember which.

Live streaming works fine in the Arlo portal with both Video and Audio.

One other note, I must not have had my volume up on my computer, because Live Streaming in HASS has both Audio and Video. Playback is still audio only (however playback works fine on my iPhone using the Home Assistant app). I believe this still links back to most modern browsers don't support HEVC.

@twrecked
Copy link
Owner

@ssilence5 See this, somebody tweaked a setting and got their library to work.

@Kras-s-savchiK
Copy link

Sorry, but I don't understood something:
Right now Video work, but without audio.

In Configuration im add line:
user_agent: linux
and right now I have this:
aarlo:
username: ***
password: ***
refresh_devices_every: 2
stream_timeout: 240
user_agent: linux

Also im added line
play_direct: true
to aarlo-glance cards.
and there I have this:
**battery_id: sensor.entrance_camera_battery
entity: camera.aarlo_door
image_click: play
play_direct: true
name: Door
show:

  • snapshot
  • battery_level
  • signal_strength
  • captured_today
    stream: null
    top_date: false
    top_status: false
    top_title: false
    type: 'custom:aarlo-glance'**

But this is don't work
Also im try to delete
stream: null
But video and audio don't work again
what im doing wrong?

@twrecked
Copy link
Owner

@Kras-s-savchiK what kind of cameras do you have?

I can't really tell from you config what is wrong because the indentation is funny. Can you try re-posting with back ticks - see here - for formatting.

@Kras-s-savchiK
Copy link

Im use Arlo Pro 2

In Configuration im add line:

user_agent: linux

and right now I have this:

aarlo:
username: ***
password: ***
refresh_devices_every: 2
stream_timeout: 240
user_agent: linux

Also im added line

play_direct: true

to aarlo-glance cards.
and there I have this:

battery_id: sensor.entrance_camera_battery
entity: camera.aarlo_door
image_click: play
play_direct: true
name: Door
show:
  - snapshot
  - battery_level
  - signal_strength
  - captured_today
stream: null
top_date: false
top_status: false
top_title: false
type: 'custom:aarlo-glance'

But this is don't work
Also im try to delete

stream: null

But video and audio don't work again

Thanks for answering

@twrecked
Copy link
Owner

Thanks.

The stream: null doesn't do anything and will be ignored, the rest of your config looks good. Are the entity_id and battery_id correct, if you don't explicitly rename the devices Aarlo gives you you don't need to specify the battery_id.

I have those cameras and they are working for me. Can you capture some debug? I want to make sure the stream is starting.

What OS and browser are you using?

logger:
  default: info
  logs:
    custom_components.aarlo: debug
    custom_components.aarlo.camera: debug
    pyaarlo: debug

Start your stream and look in homeassistant.log for startUserStream and url=https:XXX. Look if there are any errors around that.

@Kras-s-savchiK
Copy link

Im using Safari (Mac and iPhone/iPad) and iOS App
Already in config.yaml I have

media_player:
  - platform: aarlo

ffmpeg: 

stream:

Maybe, them broke to play video and sound?

@Kras-s-savchiK
Copy link

Im using Safari (Mac and iPhone/iPad) and iOS App
Already in config.yaml I have

media_player:
  - platform: aarlo

ffmpeg: 

stream:

Maybe, them broke to play video and sound?

I find some issue - I just push on 3 point in right upper corner and do reload resources

And I delete user_agent: linux and right now my cameras playing, but without sound. (

@twrecked
Copy link
Owner

Can you check here and see if it lines up with your experience. I don't have a Mac so can't readily test that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

9 participants