time4tea / gopro-dashboard-overlay

Programs to process GoPro MP4 & Generic GPX/FIT files and create video dashboards & maps
GNU General Public License v3.0
365 stars 51 forks source link

Support for GoPro Hero 12 #193

Closed grewhit25 closed 1 month ago

grewhit25 commented 5 months ago

Thank you for developing and maintaining gopro-dashboard-overlay! It's a valuable tool for cyclists like me who use GoPros to capture rides.

I use a GoPro Hero 12 action camera and a Garmin Edge 1040 cycle computer for recording my ride activity. The Hero 12 lacks built-in GPS, but fortunately, detailed ride metrics are available from the Garmin.

gopro-dashboard-overlay seems like a perfect tool to create video overlays with cycling metrics. However, the software currently doesn't support the Hero 12. Would you consider adding support for this model in a future release please? It would be greatly appreciated.

If technical differences between the Hero 12 and previous models impact support, any information available would be happy to help.

gopro-join.py was briefly explored for file concatenation, but it wasn't compatible with the Hero 12's non-continuous recording style. Additionally, the --gpx option with the Garmin Edge file and video resulted in the GPX file being ignored.

Some success was achieved by creating a video using the GPX file and the --use-gpx-only option to overlay the data, a more integrated solution within gopro-dashboard-overlay would be ideal.

I have tried a few things, output below, which maybe be useful.:

Because of battery limitations I have been stopping and starting recordings creating multiple clips for the duration of my rides.

I have a folder with a list of files, here is an example:


GX010002.MP4
GX010003.MP4
GX010004.MP4
GX010005.MP4
GX010006.MP4
GX010007.MP4
GX010008.MP4
GX010009.MP4
GX010010.MP4
GX010011.MP4
GX010012.MP4

gopro-join.py output
Notice that the files are not concatenated probably due to stream 02 not being reconignized. gopro-join.py /infile/GX010002.MP4 /work/myoutput.mp4 ```shell + program=gopro-join.py + shift + '[' gopro-join.py == '' ']' + '[' '!' -e /venv/bin/gopro-join.py ']' ++ ls -ldn . ++ awk '{print $3}' + uid=0 ++ awk '{print $4}' ++ ls -ldn . + gid=0 + '[' 0 -ne 0 ']' + /venv/bin/gopro-join.py /infile/GX010002.MP4 /work/myoutput.mp4 Found: ['GX010002.MP4'] [concat @ 0x564930a1d480] Could not find codec parameters for stream 2 (Unknown: none): unknown codec Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options Input #0, concat, from '/tmp/tmpekqxyy_9': Duration: N/A, start: 0.000000, bitrate: 45069 kb/s Stream #0:0(eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 3840x2160 [SAR 1:1 DAR 16:9], 44830 kb/s, 29.97 fp s, 29.97 tbr, 30k tbn Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro H.265 vendor_id : [0][0][0][0] encoder : GoPro H.265 encoder timecode : 08:11:26;14 Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro AAC vendor_id : [0][0][0][0] timecode : 08:11:26;14 Stream #0:2: Unknown: none Stream #0:3(eng): Data: bin_data (gpmd / 0x646D7067), 49 kb/s Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro MET Output #0, mp4, to '/work/myoutput.mp4': Metadata: encoder : Lavf60.3.100 Stream #0:0(eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 3840x2160 [SAR 1:1 DAR 16:9], q=2-31, 44830 kb/s, 29.97 fps, 29.97 tbr, 30k tbn Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro H.265 vendor_id : [0][0][0][0] encoder : GoPro H.265 encoder timecode : 08:11:26;14 Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro AAC vendor_id : [0][0][0][0] timecode : 08:11:26;14 Stream #0:2(eng): Data: bin_data (gpmd / 0x646D7067), 49 kb/s Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro MET Stream mapping: Stream #0:0 -> #0:0 (copy) Stream #0:1 -> #0:1 (copy) Stream #0:3 -> #0:2 (copy) Press [q] to stop, [?] for help frame= 8326 fps=1838 q=-1.0 Lsize= 1528669kB time=00:04:37.77 bitrate=45082.3kbits/s speed=61.3x video:1520324kB audio:6419kB subtitle:0kB other streams:1686kB global headers:0kB muxing overhead: 0.015646% ```
mygopro-join.sh output
I created a join script in the short term. Here is the output from the script: I’ve only shown output from the first two files concatenation and also not the final output of the join because it takes a long time. ```shell mygopro2-join.py /infile/GX010002.MP4 /work/myoutput.mp4 Pattern: /infile/GX*MP4 Detected files: ['/infile/GX010002.MP4', '/infile/GX010003.MP4', '/infile/GX010004.MP4', '/infile/GX010005.MP4', '/infile/GX010006. MP4', '/infile/GX010007.MP4', '/infile/GX010008.MP4', '/infile/GX010009.MP4', '/infile/GX010010.MP4', '/infile/GX010011.MP4', '/inf ile/GX010012.MP4'] ffmpeg version 6.0-6ubuntu1 Copyright (c) 2000-2023 the FFmpeg developers built with gcc 13 (Ubuntu 13.2.0-2ubuntu1) configuration: --prefix=/usr --extra-version=6ubuntu1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/inclu de/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass - -enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enabl e-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libglslang --enable-libgme --enable-libgsm --enable-libjack --ena ble-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librist --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --e nable-libssh --enable-libsvtav1 --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --ena ble-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --ena ble-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --disable-sndio --enable-libjxl --enable-pocketsphinx --enabl e-librsvg --enable-libvpl --disable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-fr ei0r --enable-libx264 --enable-libplacebo --enable-librav1e --enable-shared libavutil 58. 2.100 / 58. 2.100 libavcodec 60. 3.100 / 60. 3.100 libavformat 60. 3.100 / 60. 3.100 libavdevice 60. 1.100 / 60. 1.100 libavfilter 9. 3.100 / 9. 3.100 libswscale 7. 1.100 / 7. 1.100 libswresample 4. 10.100 / 4. 10.100 libpostproc 57. 1.100 / 57. 1.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/infile/GX010002.MP4': Metadata: major_brand : mp41 minor_version : 538120216 compatible_brands: mp41 creation_time : 2024-04-07T07:11:26.000000Z firmware : H23.01.02.20.00 Duration: 00:04:37.81, start: 0.000000, bitrate: 45085 kb/s Stream #0:0[0x1](eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 3840x2160 [SAR 1:1 DAR 16:9], 44830 kb/s, 29. 97 fps, 29.97 tbr, 30k tbn (default) Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro H.265 encoder : GoPro H.265 encoder [368/408] timecode : 08:11:26;14 Stream #0:1[0x2]: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default) Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro AAC vendor_id : [0][0][0][0] timecode : 08:11:26;14 Stream #0:2[0x3](eng): Data: none (tmcd / 0x64636D74) (default) Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro TCD timecode : 08:11:26;14 Stream #0:3[0x4](eng): Data: bin_data (gpmd / 0x646D7067), 49 kb/s (default) Metadata: creation_time : 2024-04-07T07:11:26.000000Z handler_name : GoPro MET Input #1, mov,mp4,m4a,3gp,3g2,mj2, from '/infile/GX010003.MP4': Metadata: major_brand : mp41 minor_version : 538120216 compatible_brands: mp41 creation_time : 2024-04-07T07:19:54.000000Z firmware : H23.01.02.20.00 Duration: 00:00:42.48, start: 0.000000, bitrate: 45087 kb/s Stream #1:0[0x1](eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 3840x2160 [SAR 1:1 DAR 16:9], 44828 kb/s, 29. 97 fps, 29.97 tbr, 30k tbn (default) Metadata: creation_time : 2024-04-07T07:19:54.000000Z handler_name : GoPro H.265 vendor_id : [0][0][0][0] encoder : GoPro H.265 encoder timecode : 08:19:54;24 Stream #1:1[0x2]: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default) Metadata: creation_time : 2024-04-07T07:19:54.000000Z handler_name : GoPro AAC vendor_id : [0][0][0][0] timecode : 08:19:54;24 Stream #1:2[0x3](eng): Data: none (tmcd / 0x64636D74) (default) Metadata: creation_time : 2024-04-07T07:19:54.000000Z handler_name : GoPro TCD timecode : 08:19:54;24 Stream #1:3[0x4](eng): Data: bin_data (gpmd / 0x646D7067), 49 kb/s (default) Metadata: creation_time : 2024-04-07T07:19:54.000000Z handler_name : GoPro MET Stream mapping: Stream #0:0 (hevc) -> concat Stream #0:1 (aac) -> concat Stream #1:0 (hevc) -> concat Stream #1:1 (aac) -> concat Stream #2:0 (hevc) -> concat Stream #2:1 (aac) -> concat Stream #3:0 (hevc) -> concat Stream #3:1 (aac) -> concat Stream #4:0 (hevc) -> concat Stream #4:1 (aac) -> concat Stream #5:0 (hevc) -> concat Stream #5:1 (aac) -> concat Stream #6:0 (hevc) -> concat Stream #6:1 (aac) -> concat Stream #7:0 (hevc) -> concat Stream #7:1 (aac) -> concat Stream #8:0 (hevc) -> concat Stream #8:1 (aac) -> concat Stream #9:0 (hevc) -> concat Stream #9:1 (aac) -> concat Stream #10:0 (hevc) -> concat Stream #10:1 (aac) -> concat concat:out:v0 -> Stream #0:0 (libx264) concat:out:a0 -> Stream #0:1 (aac) press [q] to stop, [?] for help [libx264 @ 0x55cbe7aa5300] using SAR=1/1 [libx264 @ 0x55cbe7aa5300] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 0x55cbe7aa5300] profile High, level 5.1, 4:2:0, 8-bit [libx264 @ 0x55cbe7aa5300] 264 - core 164 r3095 baee400 - H.264/MPEG-4 AVC codec - Copyleft 2003-2022 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00 Output #0, mp4, to '/work/myoutput.mp4': Metadata: major_brand : mp41 minor_version : 538120216 compatible_brands: mp41 firmware : H23.01.02.20.00 encoder : Lavf60.3.100 Stream #0:0: Video: h264 (avc1 / 0x31637661), yuvj420p(pc, bt709, progressive), 3840x2160 [SAR 1:1 DAR 16:9], q=2-31, 29.97 fps, 30k tbn Metadata: encoder : Lavc60.3.100 libx264 Side data: cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s Metadata: encoder : Lavc60.3.100 aac frame= 1170 fps=8.3 q=29.0 size= 364544kB time=00:00:41.06 bitrate=72719.4kbits/s speed=0.291x [0] 0:bash* [q] command received Exiting. ```
gopro-dashboart --gpx output
```bash gopro-dashboard.py --gpx /gpx/mygarmin_gpx.gpx /infile/GX010002.MP4 /workspace/myoutput.mp4 + program=gopro-dashboard.py + shift + '[' gopro-dashboard.py == '' ']' + '[' '!' -e /venv/bin/gopro-dashboard.py ']' ++ ls -ldn . ++ awk '{print $3}' + uid=0 ++ ls -ldn . ++ awk '{print $4}' + gid=0 + '[' 0 -ne 0 ']' + /venv/bin/gopro-dashboard.py --gpx /gpx/mygarmin_gpx.gpx /infile/GX010002.MP4 /workspace/myoutput.mp4 Starting gopro-dashboard version 0.125.0 ffmpeg version is 6.0-6ubuntu1 Using Python version 3.11.6 (main, Oct 8 2023, 05:06:43) [GCC 13.2.0] Loading GoPro Data Track: 1,726,736 [ 1.6 MiB] [ 41.5 MiB/s] Timer(GPMD - Called: 1, Total: 0.05431, Avg: 0.05431, Rate: 18.41) >> Can't find any GPS information Timer(extract GPS - Called: 1, Total: 0.01223, Avg: 0.01223, Rate: 81.76) Timer(parsing - Called: 1, Total: 0.06662, Avg: 0.06662, Rate: 15.01) No GPS Information found in the Video - Was GPS Recording enabled? If you have a GPX File, See https://github.com/time4tea/gopro-dashboard-overlay/tree/main/docs/bin#create-a-movie-from-gpx-and-video-not-created-with-gopro ```
time4tea commented 5 months ago

Hiya - thanks for your interest in the software! Yes the Hero 12 was a bit of an unexpected curveball, with no GPS.

grewhit25 commented 5 months ago

Hi @time4tea,

I have sent some info over as requested above. There is absolutely no pressure for you to provide any support on this issue.

Please let me know if I can be of any further assistance. I am also happy for you to just point me in the right direction.

time4tea commented 5 months ago

Thanks! - I've downloaded the files. I'll take a look and see if there is some way to make it work a bit better!

victorlysak commented 1 month ago

I use GP11. Its gps is crap - the car stopped but its gps shows that it was still moving some 100m in different directions. Maybe this is why they dropped gsp in GP12. You cannot pack the same 700 USD quality device into the tiny camera.

So, to have overlays later, for gps I use my own gps device that creates .gpx file with the <trkpt every second, like your Garmin does.

I later create overlay videos from that .gpx and then sync them with my GP11 videos that are 5k50fps. I sync them according to the speed and fine adjust on sharp curves, if there are any. Works very well.

I don't believe that you can sync .gpx data with the video based on the time stamp only. There is no way your camera and the separate gps device, even when time synced at the start of the recording, will have exactly the same time stamp up to the very second.

So, either provide constant power to the camera for cont. recording, or sync the data when you make the video with the overlays - it's easy.

grewhit25 commented 1 month ago

Thanks for the detailed explanation things are a bit clearer to me now.

I happen for this issue to be closed.

grewhit25 commented 1 month ago

I am now able to create overlays using my Garmin gpx/fit file then sync to my GoPro videos.

victorlysak commented 1 month ago

I am now able to create overlays using my Garmin gpx/fit file then sync to my GoPro videos.

Actually, with your gps device, that has lcd screen, and probably shows the time, in particular seconds, the sync should be done very easily. Every time you start recording in your camera, just put the device in front of the camera so that you can see the seconds changing, then later, when you edit your videos: look at the clip, note the exact time, open the .gpx file, remove the first lines up to the time shown in the video, and you'll have the perfect sync.

Another way I can think of is probably even more effective. You can just start your recording in your gps device at exactly the same time when you press the camera button.

Also. Can you paste here a few first lines of the .gpx file from your Garmin device to see the structure and what data each line contains.

I have much cheaper, Arduino Uno based device that creates and updates .gpx files every second, and inside it looks like this:

<gpx version="1.1">
<trk>
<name>Route.gpx</name>
<trkseg>
<trkpt lat="46.31538800" lon="7.97877790"><ele>664</ele><time>2024-06-20T10:18:04Z</time><sat>6</sat></trkpt>
<trkpt lat="46.31536500" lon="7.97866390"><ele>665</ele><time>2024-06-20T10:18:05Z</time><sat>6</sat></trkpt>
<trkpt lat="46.31534200" lon="7.97855660"><ele>665</ele><time>2024-06-20T10:18:06Z</time><sat>6</sat></trkpt>
<trkpt lat="46.31532300" lon="7.97846030"><ele>665</ele><time>2024-06-20T10:18:07Z</time><sat>7</sat></trkpt>