GoPro Flat Mount

I’ve had GoPro mounts fixed to either side of the boom of the sail boat I race on for several years. I primarily use the one on the starboard side, producing videos of races like the one below.

Last week the camera got caught in the reefing line as we raised the main sail, pulling the sticky mount completely off the boom. From past experience dropping the Gopro on the boat, I use a safety cord tied to the camera, so did not lose the camera.

This week I visited the boat the day before our race and installed a new mount on the boom. I also made sure that the reefing lines were resting on the port side of the boom so the camera wouldn’t be caught during the raise.

Soon after we had raised the main and taken a couple of tacks, the camera had shaken itself off the boom. The sticky pad didn’t stay stuck to the boom.

After I got home, I peeled the remainder of the sticky pad from the old mount with a lot of effort. I was able to peel the sticky pad from the new mount easily and in one piece.

The old mount is top right, the new mount is bottom left. An unused mount from my GoPro box is bottom right.

At one time I purchased a bunch of GoPro mounts in a kit from Amazon. The kit had a chest strap that was significantly cheaper than the original GoPro branded one. It was worth the price for me. I noticed that if I kept the new items in a Ziploc bag, the plastic had a distinct smell, while the original GoPro plastic did not. Knowing what I do about plastics, I didn’t want to trust my GoPro to the cheap plastic, unfortunately after having things sit around for a couple seasons I forgot that.

I believe the mount with the voids under the groove edges are from the inexpensive package. Along with questionable plastic, I believe it also used a less sticky adhesive pad.

I’ll try replacing the mount with the remaining original this coming week and hopefully be able to record another race

Using FFMPEG to Concatenate and Embed Subtitles

I recently upgraded my drone to a DJI Mavic Air 2. Among other things, it can create h.265 videos directly. It still uses the MP4 container format and the separate SRT format for storing video subtitles, the flight data. Following most camera standards, it creates video files that are individually smaller than 4 GB, which works out to be about five minutes in 4k video.

If I want to upload a longer raw video to social media, the video files need to be concatenated before uploading.

Concatenating the video with FFMPEG has been something I’ve known how to do for a long time using either of two methods. Today I learned how to properly embed the subtitles in either the MKV or MP4 container format.

The MP4 format is more widely supported than the MKV format, but is less flexible as to what it can contain.  The MKV (Matroska Multimedia Container) container format can hold almost any type of media, and so I’m able to copy the SRT format directly. The MP4 (MPEG-4 Part 14) container format only supports a limited selection of subtitle formats, so I’m required to have FFMPEG convert the SRT stream to a MP4 compatible stream.  If you are interested in video container formats, these tables are very helpful.

I’ll give several examples using the two video files and their associated subtitle files created by the drone named DJI00001.MP4, DJI00002.MP4, DJI00001.SRT, and DJI00002.SRT. The method I’m using should work for any number of files, up to the largest filesize you can store on your filesystem.

To simply concatenate the video files, create a text input file (I’m using mp4files.txt) with the contents as follows

file DJI00001.MP4
file DJI00001.MP4

then use the ffmpeg command to create a new concatenated file.

ffmpeg -f concat -safe 0 -i mp4files.txt -c copy ConcatenatedVideo.MP4

If you want to embed the subtitles, you need to create a second text file, do some stream mapping, and specify what format the subtitles should be. In this case I’m using srtfiles.txt

file DJI00001.SRT
file DJI00002.SRT

My FFMPEG command to create an MP4 file gets a lot more involved because now I’m specifying multiple inputs and have to specify the subtitle format.

ffmpeg -f concat -safe 0 -i mp4files.txt -f concat -safe 0 -i srtfiles.txt -map 0:v -map 1 -c:v copy -c:s mov_text ConcatenatedVideo.MP4

The FFMPEG command to create an MKV command is only a tiny bit different, and the resulting file is only a tiny bit smaller.

ffmpeg -f concat -safe 0 -i mp4files.txt -f concat -safe 0 -i srtfiles.txt -map 0:v -map 1 -c:v copy -c:s copy ConcatenatedVideo.MKV

When playing the ConcatenatedVideo files on my local machine, I can now enable or disable the closed caption track properly in the player for either format. Unfortunately in my initial testing with YouTube, neither format maintains the second stream of subtitles.

This is not all a waste of time and effort, because an advantage of embedding the subtitles into the container format is that the timing has been matched to the video, and can now be extracted in a concatenated form for use with YouTube.

ffmpeg -i ConcatenatedVideo.MKV -c copy ConcatenatedVideo.SRT

You can exclude the “-c copy” when extracting the subtitles and FFMPEG fill run it through its subrip codec and produce nearly identical results. It will only work with the MKV file because the subtitle format stored in the MP4 file is not easily converted to a SRT file.

Using the -f concat option invokes the concat demuxer in FFMPEG, which has the limitation that the format needs to be exactly the same for each file. If there are any changes between files you want to concatenate, you must use a more involved command invoking the concat filter. In a different project I ran into a command issue with the concat filter command when the command got to be much over 900 characters long.

 

Raspberry Pi ZeroW Camera Focus with FFMPEG

I wanted a quick and dirty method to test my camera module installation on my Raspberry Pi ZeroW installation. I don’t have a monitor connected to the Raspberry, and explicitly did not install the desktop version of the operating system. This is especially important because the camera itself may not be properly focused after installation in the case, and the only way to easily focus the camera is with a video stream allowing you to make small adjustments and see them nearly real time.

I’ve used FFMPEG for years as it handles almost any kind of video or audio I can throw at it. I use VLC on my desktop machine for similar reasons.

I did a quick install of ffmpeg on my Pi with the following command, allowing it to install all the requirements, adding up to almost 126 new packages and 56MB that needed to be downloaded and installed.

sudo apt-get install ffmpeg -y

After it finished installing, I was able to run the following command with the 192.168.0.16 address being my desktop computer.

ffmpeg -f video4linux2 -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -an -f mpegts udp://192.168.0.16:5000?pkt_size=1316

On my desktop computer I ran VLC, under the Media menu, selected Open Network Stream, and opened:

udp://@0.0.0.0:5000

2019-09-23 (1)2019-09-23 (2)

What I’m doing is to use FFMPEG to pull video from the device and push it using UDP datagrams at my desktop on port 5000. Then VLC opens a port on the local machine at port 5000 to receive the datagrams and it decodes and displays the video. An interesting thing about this method is that I can stop transmitting from the raspberry, then restart it, and VLC will accept the packets since UDP is a connectionless protocol.

What really surprised me was that when I logged in a second time to my Raspberry Pi to view the CPU usage for streaming, it was only running around 12% of the CPU. I was interested in knowing what native formats the camera supported..

ffmpeg -f v4l2 -list_formats all -i /dev/video0
ffmpeg version 4.1.4-1+rpt1~deb10u1 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8 (Raspbian 8.3.0-6+rpi1)
  configuration: --prefix=/usr --extra-version='1+rpt1~deb10u1' --toolchain=hardened --libdir=/usr/lib/arm-linux-gnueabihf --incdir=/usr/include/arm-linux-gnueabihf --arch=arm --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-omx-rpi --enable-mmal --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  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
[video4linux2,v4l2 @ 0x2367e40] Raw       :     yuv420p :     Planar YUV 4:2:0 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       :     yuyv422 :           YUYV 4:2:2 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       :       rgb24 :     24-bit RGB 8-8-8 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Compressed:       mjpeg :            JFIF JPEG : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Compressed:        h264 :                H.264 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Compressed:       mjpeg :          Motion-JPEG : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       : Unsupported :           YVYU 4:2:2 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       : Unsupported :           VYUY 4:2:2 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       :     uyvy422 :           UYVY 4:2:2 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       :        nv12 :         Y/CbCr 4:2:0 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       :       bgr24 :     24-bit BGR 8-8-8 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       :     yuv420p :     Planar YVU 4:2:0 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       : Unsupported :         Y/CrCb 4:2:0 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x2367e40] Raw       :        bgr0 : 32-bit BGRA/X 8-8-8-8 : {32-3280, 2}x{32-2464, 2}
/dev/video0: Immediate exit requested

That output leads me to believe that the camera module could output either h264 or mjpeg without significant CPU overhead. What it doesn’t do is tell me efficient frame sizes. It seems to say that horizontal and vertical sizes can be anything between 32 to 3280 and 32 to 2464. I know that the specs on the camera say that it will run still frames at the high resolution, but video is significantly less.

Two Video4Linux commands that return interesting and similar results are:

pi@WimPiZeroCamera:~ $ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YU12' (Planar YUV 4:2:0)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [1]: 'YUYV' (YUYV 4:2:2)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [2]: 'RGB3' (24-bit RGB 8-8-8)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [3]: 'JPEG' (JFIF JPEG, compressed)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [4]: 'H264' (H.264, compressed)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [5]: 'MJPG' (Motion-JPEG, compressed)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [6]: 'YVYU' (YVYU 4:2:2)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [7]: 'VYUY' (VYUY 4:2:2)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [8]: 'UYVY' (UYVY 4:2:2)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [9]: 'NV12' (Y/CbCr 4:2:0)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [10]: 'BGR3' (24-bit BGR 8-8-8)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [11]: 'YV12' (Planar YVU 4:2:0)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [12]: 'NV21' (Y/CrCb 4:2:0)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
        [13]: 'BGR4' (32-bit BGRA/X 8-8-8-8)
                Size: Stepwise 32x32 - 3280x2464 with step 2/2
pi@WimPiZeroCamera:~ $ v4l2-ctl -L

User Controls

                     brightness 0x00980900 (int)    : min=0 max=100 step=1 default=50 value=50 flags=slider
                       contrast 0x00980901 (int)    : min=-100 max=100 step=1 default=0 value=0 flags=slider
                     saturation 0x00980902 (int)    : min=-100 max=100 step=1 default=0 value=0 flags=slider
                    red_balance 0x0098090e (int)    : min=1 max=7999 step=1 default=1000 value=1000 flags=slider
                   blue_balance 0x0098090f (int)    : min=1 max=7999 step=1 default=1000 value=1000 flags=slider
                horizontal_flip 0x00980914 (bool)   : default=0 value=0
                  vertical_flip 0x00980915 (bool)   : default=0 value=0
           power_line_frequency 0x00980918 (menu)   : min=0 max=3 default=1 value=1
                                0: Disabled
                                1: 50 Hz
                                2: 60 Hz
                                3: Auto
                      sharpness 0x0098091b (int)    : min=-100 max=100 step=1 default=0 value=0 flags=slider
                  color_effects 0x0098091f (menu)   : min=0 max=15 default=0 value=0
                                0: None
                                1: Black & White
                                2: Sepia
                                3: Negative
                                4: Emboss
                                5: Sketch
                                6: Sky Blue
                                7: Grass Green
                                8: Skin Whiten
                                9: Vivid
                                10: Aqua
                                11: Art Freeze
                                12: Silhouette
                                13: Solarization
                                14: Antique
                                15: Set Cb/Cr
                         rotate 0x00980922 (int)    : min=0 max=360 step=90 default=0 value=0 flags=modify-layout
             color_effects_cbcr 0x0098092a (int)    : min=0 max=65535 step=1 default=32896 value=32896

Codec Controls

             video_bitrate_mode 0x009909ce (menu)   : min=0 max=1 default=0 value=0 flags=update
                                0: Variable Bitrate
                                1: Constant Bitrate
                  video_bitrate 0x009909cf (int)    : min=25000 max=25000000 step=25000 default=10000000 value=10000000
         repeat_sequence_header 0x009909e2 (bool)   : default=0 value=0
            h264_i_frame_period 0x00990a66 (int)    : min=0 max=2147483647 step=1 default=60 value=60
                     h264_level 0x00990a67 (menu)   : min=0 max=11 default=11 value=11
                                0: 1
                                1: 1b
                                2: 1.1
                                3: 1.2
                                4: 1.3
                                5: 2
                                6: 2.1
                                7: 2.2
                                8: 3
                                9: 3.1
                                10: 3.2
                                11: 4
                   h264_profile 0x00990a6b (menu)   : min=0 max=4 default=4 value=4
                                0: Baseline
                                1: Constrained Baseline
                                2: Main
                                4: High

Camera Controls

                  auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=0 value=0
                                0: Auto Mode
                                1: Manual Mode
         exposure_time_absolute 0x009a0902 (int)    : min=1 max=10000 step=1 default=1000 value=1000
     exposure_dynamic_framerate 0x009a0903 (bool)   : default=0 value=0
             auto_exposure_bias 0x009a0913 (intmenu): min=0 max=24 default=12 value=12
                                0: -4000 (0xfffffffffffff060)
                                1: -3667 (0xfffffffffffff1ad)
                                2: -3333 (0xfffffffffffff2fb)
                                3: -3000 (0xfffffffffffff448)
                                4: -2667 (0xfffffffffffff595)
                                5: -2333 (0xfffffffffffff6e3)
                                6: -2000 (0xfffffffffffff830)
                                7: -1667 (0xfffffffffffff97d)
                                8: -1333 (0xfffffffffffffacb)
                                9: -1000 (0xfffffffffffffc18)
                                10: -667 (0xfffffffffffffd65)
                                11: -333 (0xfffffffffffffeb3)
                                12: 0 (0x0)
                                13: 333 (0x14d)
                                14: 667 (0x29b)
                                15: 1000 (0x3e8)
                                16: 1333 (0x535)
                                17: 1667 (0x683)
                                18: 2000 (0x7d0)
                                19: 2333 (0x91d)
                                20: 2667 (0xa6b)
                                21: 3000 (0xbb8)
                                22: 3333 (0xd05)
                                23: 3667 (0xe53)
                                24: 4000 (0xfa0)
      white_balance_auto_preset 0x009a0914 (menu)   : min=0 max=9 default=1 value=1
                                0: Manual
                                1: Auto
                                2: Incandescent
                                3: Fluorescent
                                4: Fluorescent H
                                5: Horizon
                                6: Daylight
                                7: Flash
                                8: Cloudy
                                9: Shade
            image_stabilization 0x009a0916 (bool)   : default=0 value=0
                iso_sensitivity 0x009a0917 (intmenu): min=0 max=4 default=0 value=0
                                0: 0 (0x0)
                                1: 100000 (0x186a0)
                                2: 200000 (0x30d40)
                                3: 400000 (0x61a80)
                                4: 800000 (0xc3500)
           iso_sensitivity_auto 0x009a0918 (menu)   : min=0 max=1 default=1 value=1
                                0: Manual
                                1: Auto
         exposure_metering_mode 0x009a0919 (menu)   : min=0 max=2 default=0 value=0
                                0: Average
                                1: Center Weighted
                                2: Spot
                     scene_mode 0x009a091a (menu)   : min=0 max=13 default=0 value=0
                                0: None
                                8: Night
                                11: Sports

JPEG Compression Controls

            compression_quality 0x009d0903 (int)    : min=1 max=100 step=1 default=30 value=30

 

 

vcpkg, OpenCV, and Visual Studio

Several years ago I was playing around with a Logitech C920 webcam using OpenCV on Linux.

Recently I decided I wanted to get the same basic functionality under windows with minimal effort, so looked into what it would take to get OpenCV running on windows. I was amazed to come across a YouTube video showing the use of vcpkg as a library package manager under windows that allowed downloading, building, and installing many common libraries quite easily.

I was nicely amazed at how it worked..  Issuing just a few commands in powershell I was able to quickly download and build both vcpkg and OpenCV.

cd .\Source\Repos\
git clone https://github.com/Microsoft/vcpkg.git
cd .\vcpkg\
.\bootstrap-vcpkg.bat
.\vcpkg.exe integrate install
.\vcpkg.exe install opencv
.\vcpkg.exe install opencv:x64-windows

The one thing that bothers me the most is that I now have used over 7GB of space on my local drive on my 256GB SSD. That estimate is according to a quick change directory into the vcpkg directory and running the command dir /s /w it returned:

     Total Files Listed:
36549 File(s)  7,296,147,088 bytes
21911 Dir(s)  79,514,853,376 bytes free

My old program from Linux was able to run in my current Windows 10 environment with the only code change required being replacing the unix sleep() command with an appropriate windows command.

Here’s what the entire install process looked like in the shell:

vcpkg-1vcpkg-2vcpkg-3vcpkg-4vcpkg-5vcpkg-6

Part 4 of ROAV Dash Cam C1 Pro

I’d figured out that a 128 GB micro sd card would yield about 16 hours of video on the ROAV Dashcam which was good enough that I could make most of my daily long drives without overwriting anything.

MicroSD-128

I had a PNY 128 GB drive that I’d been using in my GoPro so I put it into the ROAV Dashcam. The ROAV requires the card be formatted as FAT32 and not the newer exFAT, but the dashcam was able to do the formatting.

After a couple of months of use, I got a strange error on the ROAV saying that the memry card was corrupted and it needed reformatting. Before I did that, I put the card into my computer and tried to copy all the data off it. I ran into an issue with some files being corrupted, and then found I was not able to reformat the card in the computer, as it was somehow being reported as read only.

Because there is no physical write protect slider on a micro SD card, I fired up diskpart and issued the commands that should clear the write protect status on a drive.

2018-07-22 (1)

It appeared to work, but then checking the status after issuing the command attributes clear disk readonly showed that no changes had really happened.

I’d been frustrated trying to figure this out for the past week. Then I came across an article in comp.risks that described exactly this sort of issue.

Micro SD cards silently switching to read-only when they’re “too old”

Mon, 16 Jul 2018 23:38:44 +0200

The 64G Patriot micro SD I had been using in my cell phone from mid 2014
just decided to turn itself into a read-only memory card.  From what I read,
it most likely reached its maximum number of uses, as it happens at least
with some Samsung cards too.  It would be to protect the card from losing
all its data, after its cells were erased "too many times" (limit number
depending on the card, and appearing to be in the order of 10-100k).  And
according to Internet forums, and card reviews on Amazon, it looks like it's
getting more and more common!

A very bad point is that there were no error messages at all.  I added music
files before a trip, but I had none of the new files available later so at
first I thought I didn't do it correctly (even if the transfer was fine, it
could for example have been to my card backup on an hard drive instead of
going to the actual card).  Then, despite the pictures still being taken
correctly by my phone (browsing was OK, able to delete the bad ones...), I
lost all of the new ones when my phone rebooted. So they were only in a
cache memory somewhere, but nowhere on the SD card (not found by deep
recovery tools either).  More fun, the older ones I deleted came back during
the same reboot...

I understand it would be bothering to have an error message at each card
access, but at least I would have known to change the card and would not
have lost 3 days of pictures!  So beware...

I’ve written low level code dealing with flash memory in the past, so I understand that there are only so many rewrite times each sector can handle. I’m also familiar with the differences in file systems between FAT32, exFAT and NTFS. I don’t believe MicroSD cards have any sort of wear leveling algorithms in them that a full fledged SSD has between the flash and the controller. The fact that ROAV puts their constantly changing data two levels deep in the directory structure at least means the data for the root directory isn’t the constantly erased and overwritten sector, but it does mean that the directory structure is getting re-written each time a new file is created. They probably aren’t writing the directory data to a new sector each time, but just overwriting the old location, possibly accelerating the death of the microsd card. because the cluster size on a 128GB Fat32 partition is fairly large, at least 32KB, it holds a lot of directory entries in a single sector.

I had a 200 GB card that I thought I’d replace the failed drive with. The ROAV attempted to format it but reported that it couldn’t. I’m thinking that they simply cannot handle a drive bigger than 128 GB.

MicroSD-200

Since I had a second 128GB card, I put it into the dashcam. I’ll be interested in seeing how long it takes for it to report as non-functional.

 

Part 2 of FFMPEG and ROAV Dash Cam C1 Pro

While writing my software to concatenate and speed up the video files from my ROAV Dashcam I ran into an interesting issue with FFMPEG.

The -filter_complex option seems to stop parsing it’s parameters somewhere above 960 characters on the command line. I didn’t narrow down the exact point, or go digging in the FFMPEG source code to find the size. I expect this is an arbitrary buffer size in FFMPEG. I may contribute to the source code since it fails with no explanation, even when generating a report file. Learning the FFMPEG source structure in itself is a large task, meaning that I’ve not found time to do anything beyond find a workaround.

My workaround was to recognize when the command size will get long and fall back to using the -f concat option with a temporary file listing the input files instead of using the complex filtergraph.

The advantage of the complex filtergraph is twofold. It does not require a secondary input file or any cleanup. It can deal with input files that change resolution if necessary.

Here’s an example of the complex filtergraph:

ffmpeg.exe -report -i 2018_0705_101335_006.MP4 -i 2018_0705_101635_007.MP4 -i 2018_0705_101935_008.MP4 -i 2018_0705_102235_009.MP4 -i 2018_0705_102535_010.MP4 -i 2018_0705_102835_011.MP4 -i 2018_0705_103135_012.MP4 -i 2018_0705_103435_013.MP4 -i 2018_0705_103613_014A.MP4 -i 2018_0705_103615_015A.MP4 -i 2018_0705_104449_016A.MP4 -i 2018_0705_104750_017A.MP4 -i 2018_0705_105050_018A.MP4 -i 2018_0705_105350_019A.MP4 -i 2018_0705_105650_020A.MP4 -i 2018_0705_105950_021A.MP4 -i 2018_0705_110250_022A.MP4 -i 2018_0705_110550_023A.MP4 -i 2018_0705_110850_024A.MP4 -i 2018_0705_143415_025.MP4 -i 2018_0705_143716_026.MP4 -i 2018_0705_144016_027.MP4 -i 2018_0705_144316_028.MP4 -i 2018_0705_144616_029.MP4 -i 2018_0705_144916_030.MP4 -i 2018_0705_145216_031.MP4 -i 2018_0705_145516_032.MP4 -i 2018_0705_145816_033.MP4 -i 2018_0705_150116_034.MP4 -i 2018_0705_150416_035.MP4 -i 2018_0705_150716_036.MP4 -i 2018_0705_151016_037.MP4 -i 2018_0705_151316_038.MP4 -i 2018_0705_151616_039.MP4 -i 2018_0705_151916_040.MP4 -i 2018_0705_152216_041.MP4 -i 2018_0705_152516_042.MP4 -i 2018_0705_152816_043.MP4 -i 2018_0705_153116_044.MP4 -i 2018_0705_153416_045.MP4 -i 2018_0705_153716_046.MP4 -i 2018_0705_154016_047.MP4 -i 2018_0705_154316_048.MP4 -i 2018_0705_154616_049.MP4 -i 2018_0705_154916_050.MP4 -i 2018_0705_155216_051.MP4 -i 2018_0705_155516_052.MP4 -i 2018_0705_155816_053.MP4 -i 2018_0705_160116_054.MP4 -i 2018_0705_160416_055.MP4 -i 2018_0705_160716_056.MP4 -i 2018_0705_161016_057.MP4 -i 2018_0705_161316_058.MP4 -i 2018_0705_161616_059.MP4 -i 2018_0705_161916_060.MP4 -i 2018_0705_162216_061.MP4 -i 2018_0705_162516_062.MP4 -i 2018_0705_162816_063.MP4 -i 2018_0705_163116_064.MP4 -i 2018_0705_163416_065.MP4 -i 2018_0705_163716_066.MP4 -i 2018_0705_164016_067.MP4 -i 2018_0705_164316_068.MP4 -i 2018_0705_164616_069.MP4 -i 2018_0705_164916_070.MP4 -i 2018_0705_165215_071.MP4 -i 2018_0705_165516_072.MP4 -i 2018_0705_165815_073.MP4 -i 2018_0705_170115_074.MP4 -i 2018_0705_170415_075.MP4 -i 2018_0705_170715_076.MP4 -i 2018_0705_171015_077.MP4 -i 2018_0705_171315_078.MP4 -i 2018_0705_171615_079.MP4 -i 2018_0705_171915_080.MP4 -i 2018_0705_172216_081.MP4 -i 2018_0705_172515_082.MP4 -i 2018_0705_172815_083.MP4 -i 2018_0705_173115_084.MP4 -i 2018_0705_173415_085.MP4 -i 2018_0705_173715_086.MP4 -i 2018_0705_174015_087.MP4 -i 2018_0705_174315_088.MP4 -i 2018_0705_174615_089.MP4 -i 2018_0705_174915_090.MP4 -i 2018_0705_175215_091.MP4 -i 2018_0705_175515_092.MP4 -i 2018_0705_175815_093.MP4 -i 2018_0705_180115_094.MP4 -i 2018_0705_180415_095.MP4 -i 2018_0705_180715_096.MP4 -i 2018_0705_181015_097.MP4 -i 2018_0705_181315_098.MP4 -i 2018_0705_181615_099.MP4 -i 2018_0705_181915_100.MP4 -i 2018_0705_182215_101.MP4 -i 2018_0705_182515_102.MP4 -i 2018_0705_182815_103.MP4 -i 2018_0705_183115_104.MP4 -i 2018_0705_183415_105.MP4 -i 2018_0705_183715_106.MP4 -i 2018_0705_184015_107.MP4 -i 2018_0705_184315_108.MP4 -i 2018_0705_184615_109.MP4 -i 2018_0705_184915_110.MP4 -i 2018_0705_185215_111.MP4 -i 2018_0705_185515_112.MP4 -i 2018_0705_185815_113.MP4 -i 2018_0705_190115_114.MP4 -i 2018_0705_190415_115.MP4 -filter_complex [0:v][1:v][2:v][3:v][4:v][5:v][6:v][7:v][8:v][9:v][10:v][11:v][12:v][13:v][14:v][15:v][16:v][17:v][18:v][19:v][20:v][21:v][22:v][23:v][24:v][25:v][26:v][27:v][28:v][29:v][30:v][31:v][32:v][33:v][34:v][35:v][36:v][37:v][38:v][39:v][40:v][41:v][42:v][43:v][44:v][45:v][46:v][47:v][48:v][49:v][50:v][51:v][52:v][53:v][54:v][55:v][56:v][57:v][58:v][59:v][60:v][61:v][62:v][63:v][64:v][65:v][66:v][67:v][68:v][69:v][70:v][71:v][72:v][73:v][74:v][75:v][76:v][77:v][78:v][79:v][80:v][81:v][82:v][83:v][84:v][85:v][86:v][87:v][88:v][89:v][90:v][91:v][92:v][93:v][94:v][95:v][96:v][97:v][98:v][99:v][100:v][101:v][102:v][103:v][104:v][105:v][106:v][107:v][108:v][109:v]concat=n=110:v=1[v];[v]setpts=(1/60)*PTS,drawtext=fontfile=C\\:/WINDOWS/Fonts/consola.ttf:fontcolor=white:fontsize=80:y=main_h-text_h-50:x=50:text=WimsWorld[o] -map [o] -c:v libx265 -crf 23 -preset veryfast -movflags +faststart -bf 2 -g 15 -pix_fmt yuv420p -y “Output.mp4”

Here’s an example of the command where all the input files are defined in the temporary file:

ffmpeg.exe -report -f concat -safe 0 -i C:\Users\Wim\AppData\Local\Temp\Wim4BD3.tmp -vf setpts=(1/60)*PTS,drawtext=fontfile=C\\:/WINDOWS/Fonts/consola.ttf:fontcolor=white:fontsize=80:y=main_h-text_h-50:x=50:text=WimsWorld -an -c:v libx265 -crf 23 -preset veryfast -movflags +faststart -bf 2 -g 15 -pix_fmt yuv420p -y “Output.mp4”

 

FFMPEG and ROAV Dash Cam C1 Pro

I recently purchased a dedicated dashcam on sale to replace my GoPro setup for trip videos. This gives me a new need to understand a new file format.

2018-05-18

The Roav Dashcam stores sequential mp4 files. When configuring the camera it’s possible to set the loop time, which is the duration of each mp4. There’s also an option to watermark the files. I have it turned on, and the only thing I’ve noticed is the ROAV logo, timestamp, and speed in the bottom right. It does not appear to have a way of adjusting the size of the text.

My initial recordings were set to run at 1080p 60 fps. I wanted to concatenate multiple files, add some text of my own, and speed up the video. This was my first experience using the -filter_complex option of FFMPEG. Here’s what I came up with to put together three files, speed the output up by a factor of 60, and add some text. I’m dropping the audio completely. The ROAV can record audio inside the car, but I configured it not to, as I don’t want to hear what I was listening to on the radio or what I might be saying if I make a phone call..

ffmpeg.exe -hide_banner -i 2018_0512_130537_050A.MP4 -i 2018_0512_131537_051A.MP4 -i 2018_0512_132537_052A.MP4 -filter_complex "[0:v] [1:v] [2:v] concat=n=3:v=1 [v];[v]setpts=0.01666*PTS,drawtext=fontfile=C\\:/WINDOWS/Fonts/consola.ttf:fontcolor=white:fontsize=80:y=main_h-text_h-50:x=50:text=WimsWorld[o]" -map "[o]" -c:v libx265 -crf 23 -preset veryfast -movflags +faststart -bf 2 -g 15 -pix_fmt yuv420p  FirstMixSpeed60Concat.mp4

This first video was recorded at 1080p60. The camera can record at 1440p30 which I will be trying soon to see if things like license plates are more legible. The setpts factor that I’m currently using was 1/60, so that 1 minute of real time was compressed to 1 second of video, and just dropping the extra frames. I expect to need to change the setpts factor to 1/30 because of the decreased frame rate at the higher resolution.