1

I have a security camera running Linux (busybox 1.32.0) which I can set to record video continuously in (configurable) 30 seconds chunks in a folder structure:

recording/2022/04/26/15/2022-04-26-15-30-00.mp4

In another folder, static images are recorded only when motion is detected:

stills/2022/04/26/15/2022-04-26-15-30-05.jpg

This is a workaround I made up to get videos even before a motion is detected.

Since the space available is limited, I would like to delete any video which is started more than 60 seconds before motion, and 120 seconds after motion, so that I keep some pre- and post-video for each still image.

Still images can be as frequent as every 5 seconds, since they are based on triggers by motion and not on a predefined interval.

Of course, with one single image it's a matter of running "find" with the appropriate options, but what about my more complex use case?

I thought about some possible ways but I'm not sure how to proceed.

I thought about running a script every day which lists the elements (recordings and stills) from the previous day, converts from filename to timestamp each one of them, then iteratively compares timestamps with the timestamps for the still images.

This would involve 4 lists (filenames, timestamps, for both recordings and stills) and seems to me quite involved (maybe because I'm not familiar with shell scripts), so is there an easier way to do it?

Solutions involving python or perl would require compiling it for the platform, and may impose a too high load on the CPU, not to mention that the free space on the device is already limited and a samba 4.x executable already couldn't fit.

The tools available are those available as part of busybox plus the binaries listed in the project website.

thanasisp
  • 8,122
FarO
  • 224
  • Is 2022-04-26-15-30.mp4 the video started at 2022-04-26 15:30:00? Then how is the one started at 15:30:30 named? – Stéphane Chazelas Apr 26 '22 at 15:00
  • @StéphaneChazelas my mistake, it was a typo. – FarO Apr 26 '22 at 15:18
  • 1
    Is perl available? This is fiddly to do with sh - but IFS="\0" for still in $(find stills/ -name *.jpg -print0); do would be your starting point there. You'll probably need two separate loops: one to build a list of what you're keeping, and the other to delete everything else. – OrangeDog Apr 26 '22 at 16:02
  • @OrangeDog the tools are limited: busybox plus some binaries which are not much relevant for the purpose of this script, I added the links in the question. – FarO Apr 26 '22 at 19:34
  • Can the stills be very close to each other? – thanasisp Apr 28 '22 at 02:34
  • @thanasisp Still images can be as frequent as every 5 seconds, since they are based on triggers by motion and not on a predefined interval. The script saving images is independent from the script handling the continuous 30 second recordings. – FarO Apr 28 '22 at 08:50
  • 1
    while other options are not available, date could be used to create patterns. it's limited syntax also. Without any date at all, we could blindly keep N videos before and M after a string comparison matches, (not necessarily) assuming all recordings exist (no useful data would be lost if they don't). – thanasisp Apr 28 '22 at 09:10

2 Answers2

2

Without using the consept of time at all, rely on the filenames and the fact that sorting them alphabetically is the same with sorting by time.

First step:

$ busybox sh
$ target="/2022/04/26"
$ busybox find recording/"$target" stills/"$target" -type f | busybox sort -t/ -k6 |\
busybox grep -B2 -A4 'jpg$' | busybox grep 'mp4$' > keep.txt

Get both recordings and stills for a time period with find, sort the arguments by the filename. Pictures and videos together are sorted by time now. grep for the pictures, keeping lines before and after any match (play with -B, -A to see how much you would like) and finally get only the recordings to keep.

The intermediate output of the first grep would be like this, for 2 before, 4 after:

recording/2022/04/26/15/2022-04-26-15-31-30.mp4
recording/2022/04/26/15/2022-04-26-15-32-00.mp4
stills/2022/04/26/15/2022-04-26-15-32-05.jpg
recording/2022/04/26/15/2022-04-26-15-32-30.mp4
recording/2022/04/26/15/2022-04-26-15-33-00.mp4
recording/2022/04/26/15/2022-04-26-15-33-30.mp4
recording/2022/04/26/15/2022-04-26-15-34-00.mp4
--
recording/2022/04/26/15/2022-04-26-15-36-30.mp4
recording/2022/04/26/15/2022-04-26-15-37-00.mp4
stills/2022/04/26/15/2022-04-26-15-37-29.jpg
recording/2022/04/26/15/2022-04-26-15-37-30.mp4
stills/2022/04/26/15/2022-04-26-15-37-34.jpg
recording/2022/04/26/15/2022-04-26-15-38-00.mp4
recording/2022/04/26/15/2022-04-26-15-38-30.mp4
recording/2022/04/26/15/2022-04-26-15-39-00.mp4
recording/2022/04/26/15/2022-04-26-15-39-30.mp4

Second step:

$ busybox find recording/"$target" -type f | busybox grep -vf keep.txt | busybox xargs echo rm

to exclude the files-to-keep from the recordings and remove the rest of them.


Notes:

Filenames should be flat, no spaces and special characters, I don't know if more options work for your busybox. For the version I installed and run the command, 1.34, I see -print0 exists for find, and -z for sort but not for grep, and -0 for xargs also exists.

Also we assume that all recordings exist for the target period. But even if they don't, we don't remove any useful chunks, in the worst case we could just keep a few more, e.g. if there is no video around a still, we will keep the closer chunks no matter when they are.

thanasisp
  • 8,122
  • For a time- approach, the first step would be to use date, like this to create timestamps. I saw that the full syntax is not available and I don't know if it could be slow if there are a lot of calls to date. – thanasisp Apr 29 '22 at 03:15
  • I had no idea grep could do that! What does -k6 means here? busybox sort -t/ -k6 – FarO Apr 29 '22 at 08:49
  • sort the file using the 6th field as key. -t '/' is the separator to define fields. Unfotunately sort cannot refer the fields starting numbering from the end, like awk. Use busybox sort --help to see existing options of each command. – thanasisp Apr 29 '22 at 10:32
-1

It is definitely possible using a shell script but you'll have an easier job by using Python. You can check out the os module for Python which allows you to get all the files in a directory.

Then all you have to do is compare the filename with a regex and delete the unwanted files.