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

Milliseconds support for time overlay (recording and streaming) #2130

Open
noggplotter opened this issue May 31, 2021 · 5 comments
Open

Milliseconds support for time overlay (recording and streaming) #2130

noggplotter opened this issue May 31, 2021 · 5 comments

Comments

@noggplotter
Copy link

Hi,

Great piece of software. I modified it to use without wifi to constantly monitor bat flights on a raspberry pi 3B simultaneous to audio recordings (no detection trigger used). (I use a local hotspot on my smartphone to setup the camera and check the stream).
However I need now higher precision and implemented a milisecond overlay.
In the camera-x.conf file it accepts miliseconds and also displays them in the overlay:
text_right %Y-%m-%d %T.%3N
However the overlay seems to be refreshed only every second so that I don`t really gain anything from the miliseconds since they show always the same 3 digits every second.

Therefore I used the bash script below which gets started and killed with motioneye server (c is a correction due to processing time):

#!/bin/bash
#for recording correction (s)
#c=-0.2
#for stream correction (s)
c=+0.3
NOW=$( date '+%Y-%m-%d_%H:%M:%S.%3N' )
while :
do
curl "http://localhost:7999/1/config/set?text_right=`LANG=C date '+%Y-%m-%d %H:%M:%S.%3N' --date "NOW $c sec"`"
sleep 0.01
done
exit

This unfortunately uses 20% more cpu and I`m off by about +-50ms of real time (https://time.curby.net/clock)
and it uses more energy. Since my devices are car battery powered and temperature in warm attics can play a role I would rather stay with 50% cpu usage while recording 10 minute 720p files instead of 70-80%.

See the timing in the attached picture:

image

Is there a way to change the overlay refresh interval to 10ms or 100ms in more efficient and precise way than using the above curl?
So I could use it in combination with the normal "text_right %Y-%m-%d %T.%3N" in the config file.
I saw in the monitor.py file an interesting variable:
DEFAULT_INTERVAL = 1 # seconds
I changed it to 0.1 and 2 directly in the install folder and compiled it, unfortunately without any effect. Or do I have to take additional steps beside changing the variable, compile it to a .pyc and reboot raspberry pi that the new values take effect?

Maybe my bash script can still be of use for some people if efficiency is not that important. :-)

Thanks for your help in advance.

@zagrim
Copy link
Collaborator

zagrim commented May 31, 2021

The overlay comes from Motion (which your script reconfigures over the webcontrol interface), but I have to ask what's the camera frame rate you're using? Asking for 10 ms refresh interval for the overlay would also mean having 1/0,01=100 frames/sec since the overlay is written on the video frames. Recording 720p at 100 fps using a Raspberry Pi sounds quite a challenge, too, even without any motion detection (which I assume you're not using), is that even feasible?

What I see in Motion docs is that %N stands for noise level, not fractions of seconds (and strftime docs Motion docs refer to don't contradict that). Based on that I don't think there's any built-in way in Motion to have millisecods to be displayed in the overlay, and having a script updating the config might be the only way...

Anyway, if it really is so that the timestamp in the overlay doesn't change even though there are multiple video frames per second, I think that must be some sort of optimization (or just a side-effect of something else which has gone unnoticed) in Motion. I also took a quick look at where DEFAULT_INTERVAL is being used, but I'm not quite sure how the word "monitor" in the code translates in the user interface, but I suspect it having something to do with the "Streaming frame rate" (under "Video streaming") which can be equal or less than the camera frame rate. You have turned off "Motion optimization" there as well, right?

As for changing the code, did you restart MotionEye service after recompiling (might be a stupid question but asking just to make sure 😃 )?

@noggplotter
Copy link
Author

Hey, thx for the reply. :-)

The overlay comes from Motion (which your script reconfigures over the webcontrol interface), but I have to ask what's the camera frame rate you're using? Asking for 10 ms refresh interval for the overlay would also mean having 1/0,01=100 frames/sec since the overlay is written on the video frames. Recording 720p at 100 fps using a Raspberry Pi sounds quite a challenge, too, even without any motion detection (which I assume you're not using), is that even feasible?

Of course you are right, I`m only running it 720p with 25fps. So I get a new frame every 40ms. The ideal sleep would be 0.040 s in the bash script if it would synchronize exactly at every new frame.

What I see in Motion docs is that %N stands for noise level, not fractions of seconds (and strftime docs Motion docs refer to don't contradict that). Based on that I don't think there's any built-in way in Motion to have millisecods to be displayed in the overlay, and having a script updating the config might be the only way...

Ok and my values if I use the config path with "text_right %Y-%m-%d %T.%3N" are always between 1-255 which corresponds to your explanation.

Anyway, if it really is so that the timestamp in the overlay doesn't change even though there are multiple video frames per second, I think that must be some sort of optimization (or just a side-effect of something else which has gone unnoticed) in Motion. I also took a quick look at where DEFAULT_INTERVAL is being used, but I'm not quite sure how the word "monitor" in the code translates in the user interface, but I suspect it having something to do with the "Streaming frame rate" (under "Video streaming") which can be equal or less than the camera frame rate. You have turned off "Motion optimization" there as well, right?

Yes,I just redid the whole setting Default_INTERVAL=2 and still get the overlay refreshed every second instead of every 2 seconds.
I will also check if changing some settings in camera-x.conf (see my settings at the end) will change something but motion detection should be completely turned off.

As for changing the code, did you restart MotionEye service after recompiling (might be a stupid question but asking just to make sure 😃 )?

To alter the monitor.py I used:
sudo meyectl stopserver -b -c /home/pi/motioneyestreamonly/motioneye.conf
sudo nano .local/lib/python2.7/site-packages/motioneye/monitor.py # to change DEFAULT_INTERVAL=2
sudo python -m py_compile .local/lib/python2.7/site-packages/motioneye/monitor.py #to compile
sudo meyectl startserver -b -c /etc/motioneye/motioneye.conf

And I even rebooted the rpi.

Btw, I actually do the scheduled constant recording with 10 minute files via starting and stopping the motion sever via crontab with the start and stopserver commands.

Below all the camera settings (I might turn off more to see whether I can save more cpu):
threshold_maximum 0
stream_quality 85
threshold 5997
noise_level 31
pre_capture 1
movie_codec mp4:h264_omx
noise_tune on
smart_mask_speed 0
stream_maxrate 25
stream_localhost on
text_changes off
movie_filename %Y-%m-%d/%H-%M-%S-%3N
movie_max_time 600
lightswitch_percent 0
movie_passthrough off
auto_brightness off
stream_port 8082
rotate 180
stream_auth_method 0
threshold_tune off
framerate 25
emulate_motion on
movie_output on
picture_quality 85
snapshot_filename
despeckle_filter
snapshot_interval 0
minimum_motion_frames 20
stream_motion off
target_dir /var/lib/motioneye/Camera2
movie_output_motion off
post_capture 1
stream_authentication user:
on_picture_save /usr/local/lib/python2.7/dist-packages/motioneye/scripts/relayevent.sh "/etc/motioneye/motioneye.conf" picture_save %t %f
on_movie_end /usr/local/lib/python2.7/dist-packages/motioneye/scripts/relayevent.sh "/etc/motioneye/motioneye.conf" movie_end %t %f
text_left Batcam1
picture_output_motion off
picture_filename
text_scale 2
locate_motion_style redbox
locate_motion_mode off
mmalcam_name vc.ril.camera
movie_quality 50
picture_output off
on_event_end /usr/local/lib/python2.7/dist-packages/motioneye/scripts/relayevent.sh "/etc/motioneye/motioneye.conf" stop %t
text_right %Y-%m-%d %T
on_event_start /usr/local/lib/python2.7/dist-packages/motioneye/scripts/relayevent.sh "/etc/motioneye/motioneye.conf" start %t
camera_name Batcam1
event_gap 30
height 720
mask_file
width 1280

@zagrim
Copy link
Collaborator

zagrim commented Jun 2, 2021

With some digging and luck I found the concept the DEFAULT_MONITOR constant relates to: https://github.com/ccrisan/motioneye/wiki/Monitoring-Commands . Basically that is what you migth want to be using instead of having a script running in loop alongside of ME, but indeed it seems to be designed to run things only on every second at max. And it seems like it is only shown on ME GUI over the stream (example screenshot), so if you need it "burnt" in the video stream then it a no-go.

Anyway, if you want to experiment with that, it seems like it might be possible to make it run on nanosecond precision by changing now = time.time() to now = time.time_ns() in get_monitor_infoin monitor.py and adjusting all interval related things accordingly. However, I'm not sure if that code is getting called on every video frame received or on a specific intervals. And I can't tell if that would use less CPU than your bash script (I'd bet the HTTP request part is rather heavy so a monitor command might end up being more efficient).

As for the way of recompiling ME, I run ME with modifications only in my local development environment, I don't touch my production setup other that my upgrading it with pip. Also I don't know if the procedure you mentioned should generally work or not since prior to ME I've only run Python code by having it directly execute (like scripts).

@noggplotter
Copy link
Author

I meant to reply way earlier but was carried away configuring manual ntp sync from a local windows 10 notebook for the same setup when deploying the cameras without any internet connection.

Since I need the timestamp burned into the video and I need to leave for fieldwork to deploy the cameras in 5 days I will stick with the curl version for now.
Right now its plus minus 40-50 ms accuracy which should be good enough for my purposes. :-)

Thx again for the helpful input. :-)

@Clumpton
Copy link

I would like to add a "+1" for this too. I am trying to measure the speed of cars passing pas my door and the variable framerate video is doing my head in. A ms timestamp would be a great help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants