GithubHelp home page GithubHelp logo

fxstein / goprox Goto Github PK

View Code? Open in Web Editor NEW
24.0 3.0 3.0 2.36 GB

The missing GoPro data and workflow manager for macOS

License: MIT License

Shell 100.00%
hero10 hero9 hero8 gopro max exif macos zsh apple apple-photos

goprox's Introduction

GoProX

GitHub release (latest by date including pre-releases) GitHub GitHub top language Platform GitHub labels

GitHub Workflow Status

The missing GoPro workflow and data manager for macOS.

For those with one or more GoPro cameras. When using these action cameras regularly, the limitations of the GoPro ecosystem quickly become very obvious. GoPro is focusing its efforts on its mobile app experience, and not much development is directed toward macOS. GoProX is geared toward (semi-) professionals and prosumers that simply need more from their devices. GoProX is based on a data-first approach to importing, processing and maintaining media generated by various GoPro devices. At this moment the tool is actively developed and tested with GoPro Hero8, Hero9, Hero10, Hero11 and GoPro Max.

Installation

The most common way to install goprox is via home-brew.

To install goprox simply type

brew install fxstein/fxstein/goprox

Alternatively, you can add the fxstein tap manually before installing goprox

brew tap fxstein/fxstein
brew install goprox

Once installed, you can upgrade goprox by simply running

brew upgrade goprox

Alternatively, you can also uninstall and reinstall goprox in case of issues with the upgrade

brew uninstall goprox
brew install goprox

Setup

To simplify repeat usage of goprox it supports saving its configuration in ~/.goprox. To create this configurations file, simply execute goprox with its --setup option:

goprox --setup --library "/mylibrary/dir" --source "." --copyright "My Name"

You can also create alternate configuration files by specifying the --config option:

goprox --config "myotherconfig" --setup --library "/myotherlibrary" --source "." --copyright "My Other Name"

All subsequent runs of goprox will by default leverage the setting stored in ~/.goprox unless the --config option is specified with an alternate configuration file.

The --setup option can be rerun as often as desired to change the settings stored in ~/.goprox. Whenever --setup detects a prior configuration it creates a backup copy named like .goprox.bak.1657302965. The configuration file is a simple text file that is sourced in goprox.

As part of the setup, goprox will create a library skeleton unless the library already exists. The default location is ~/goprox, but placing the library on a dedicated storage device is highly encouraged as the data volumes will be very significant.

This is the hierarchy of the goprox library:

goprox/ (named and placed as required)
├── archive/
├── imported/
├── processed/
└── deleted/

All subsequent runs of goprox will validate this storage hierarchy. See the storage hierarchy section for more details

Usage

Once installed and set up GoProX maintains a file system based media library that is organized by time, camera types and media file types. The main goal is to maintain all file details from the original to the processed items, even if media files are further being processed in various apps including e.g. Apple Photos or Blackmagic DaVinci Resolve. Unfortunately, many commonly used apps ignore most of the important metadata, making it very hard for users to filter, sort or search for common things inside ever-growing libraries of media. GoProX performs a few simple tasks that will make your life with GoPro media on Apple platforms a lot easier. First, it renames the files as part of --import and --process tasks. This is an often overlooked step that will lead to the loss of some of the most basic metadata over time. Especially when files get exported, copied or moved, things like the original date & time, and the source of the original image can get lost easily, creating issues down the line.

It then adds additional tags and keywords into the processed media files to make searching, filtering and corrections a lot easier.

GoProX supports --geonames lookups for GPS-based timezone information, --firmware checks and upgrades, --archive of raw media into compressed archives before --import and --process tasks are being applied, a --clean task to remove processed media from storage devices as well as a --timeshift task that makes it possible to bulk change the date and time information of media files. It also makes it easy to apply default --copyright tags to all processed media. Default options can be set using the --setup tasks and settings are being stored in the user's home directory in ~.goprox. The output can be timestamped via the --time option to log long-running tasks. For developers, GoProX comes with a small set of test data from various cameras that allows for testing and validation of changes with the --test option.

Examples

goprox --import

The --import option will read from source (default to the current directory .) and import all image and video media files into library\imported. This is best used for importing media files from the path of a mounted media card. To do so, insert your camera's microSD card into a reader attached to your Mac. Open Finder to see the mounted card, right-click it and select New Terminal at Folder. This will open a new zsh terminal at the mounted card folder.

Alternatively --import can process a tar.gz archive directly. It will first untar the contents into a temp directory and then import from there. This is helpful when re-importing previously archived sd card data

goprox --archive

The --archive option will create a full archive of the source folder as a tarball inside library\archive named like 20220802215621_GoPro_Hero10_2442.tar.gz. This is useful to preserve the full content of the SD card before making any changes to it.

goprox --archive --import --clean

All the options can be performed in a single pass. In this example goprox will first create a new archive of the source, then import all the media files contained on the source and finally remove all media files from the source. The --clean option will only execute when combined with either --archive or --import or both to avoid accidental deletion of media files.

goprox --firmware

The --firmware option will check the camera model and current firmware version of the sd card currently mounted and will upgrade it to the latest GoPro firmware for your model if a newer one exists. Simply put the sd card back into the camera and on the next boot up the camera will upgrade itself.

The labs modifier: goprox --firmware labs will perform the same check for the latest GoPro Labs firmware version. Omitting the labs modifier in a later firmware check will return the camera to the latest official firmware.

goprox --import --time

Adding the --time option creates a timestamped output of the goprox run to aid in logging for long-running tasks that import or process thousands of media files. All output of goprox is getting timestamped like

[2022-08-04 12:15:09] Info: goprox v00.08.08

goprox --archive --import --clean --time --firmware

This example combines the most commonly used features for any import of media files directly from the camera's sd card. --archive creates a full tarball of the content --import imports all media files into the library --clean removes all media files from the sd card upon successful completion of the --archive and --import tasks --time timestamps all goprox output --fimware checks the sd-card for the current firmware version of the camera and if necessary installs the latest firmware onto the card for an automatic upgrade next time the camera is booted up. For this to function properly sd-cards of different cameras should not be mixed.

It is recommended to perform as many import tasks as you have cameras with new footage. Multiple camera sd-card can be imported simultaneously if a multi-card reader is available.

goprox --process --time

The --process option takes unmodified imported media files and rewrites them with enhanced metadata. This is where goprox inserts tags and flags into the media files that are then picked up by the likes of Apple Photos. For GoPro video media (mp4 & 360) --process also performs a UTC timeshift of all the Quicktime tags to allow downstream tools like Apple or Google Photos to display the correct date and time.

By default, process will look for newly imported media files since the last process run. Alternatively, all or any valid time window can be specified *[0-9](y|m|w|d|H|M|S). For example, goprox --process 30d will process the past 30d while goprox --process all will process all imported media files. Caution should be used when reprocessing older media files as the content of a file will change with a newer version of goprox, as any change in metadata will lead to a modified file.

Filenames

The Filenames Mess

GoPro uses various file-naming conventions in its cameras. There is no clear structure and in most cases, you get some sort of prefix followed by a running number and a file extension.

Here are some examples of GoPro Filenames:

GOPR0001.JPG
GH010008.MP4
GX010408.MP4
GS__3305.JPG
GS013331.360

If you happen to leverage the GoPro+ Cloud it gets a lot weirder with things like

GPTempDownload.jpg

for anything GoPro Quik touches and forwards to e.g. Apple Photos.

There are many problems with these filenames - many not unique to GoPro. First of all, they are very non-descriptive. You might be able to deduct the camera model to some extent, but that's about it. No date/time in case that information gets lost somewhere along the way. But also the fact that these names are created for a world where users only ever use a single camera at the same time. As all cameras start with 0001 for the first media and continuously count up, it is only a question of time when you will run into naming conflicts with two or more cameras. That usually means one file from one camera will overwrite another file from another camera. And depending on usage each camera will eventually, in some cases even regularly, restart at 0001.

So instead of very complicated folder structures to keep images from colliding with each other, GoProX creates more sophisticated filenames that allow you to sort and act on the filenames themselves.

A better way to name files

Let's take a look at the names of the files GoProX creates on --import:

20211010090947_GoPro_Hero10_7678_GOPR0768.JPG
20160130223238_GoPro_Max_6013_GS__1596.JPG
20210615110514_GoPro_Hero9_9650_GOPR1353.JPG
20201231054457_GoPro_Hero8_1659_GOPR0129.JPG
20210731003746_GoPro_Hero9_4139_GH013340.MP4
20211011072108_GoPro_Max_6013_GS012830.360

The first 8 digits are the original date when the photo was taken, followed by 6 digits of the time, followed by the model of the camera. The for digits after that are the last four digits of the camera's serial number - to allow you to find all the media from a particular camera. Especially important if you find out after the fact that a setting was wrong in one of your cameras (Like when you find a 2016 date for GoPro Max media). Finally, the original filename and extension are added.

Right there is a wealth of information that helps with a lot of issues and even software bugs in the likes of Apple Photos that for example messes up the date & time for imported MP4 files. As the filename is kept along with the images and videos it gives you a very simple way to double-check what is going on.

.360 videos from the GoPro Max listed here cannot be imported directly into the likes of Apple Photos. You will need GoPro Player on the Mac or GoPro Quik on iOS to process them for further consumption. Alternatively, they can be used as mp4 files and processed in platforms like DaVinci Resolve or Adobe Premier with proper plugins installed.

The --process option further refines the filenames and also adds and rewrites embedded metadata. All file extensions are normalized to lowercase extensions and the files are sorted by main file type. As part of that process, .360 files become .mp4 files that are otherwise identical to the GoPro .360 format but can now be handled by most downstream applications.

Processed files get an additional P_ prefix to delineate from the unmodified imported files.

P_20210606094917_GoPro_Hero9_4139_GOPR0182.jpg
P_20210806114935_GoPro_Hero9_4139_GOPR3422.jpg
P_20220206144720_GoPro_Hero10_8034_GOPR2313.jpg
P_20220206145556_GoPro_Hero10_8034_GOPR2320.jpg
...
P_20210627102316_GoPro_Hero9_0021_GH013156.mp4
P_20211015084940_GoPro_Max_6013_GS013292.mp4

Exif & Metadata

Tags

In addition to the names of the files getting supercharged, there is a ton of information available inside the Exif metadata that macOS or Apple Photos keep intact but ignores and does not even display unless you use Preview on a particular file to inspect the metadata. Apple Photos only gives you Title, Caption and Tags to work with to store additional information aside from the most basic metadata.

This is where GoProX performs a little metadata shuffle to make at least some attributes searchable from within Apple Photos.

Several of the low cardinality Exif fields are getting converted to a list of tags. That list Apple Photos converts to its tags when importing the media.

Here is a list of tags that are being created by GoProX:

Make: ...
Camera: ...
Camera: ... ....
Software: ...
AutoRotation: ...
Orientation: ...
SceneCaptureType: ...
ProTune: ...
Sharpness: ...
MeteringMode: ...
GainControl: ...
Contrast: ...
Saturation: ...
WhiteBalance: ...
HDRSetting: ...
ExposureLockUsed: ...
ProjectionType: ...
ImageStabilization: ...

These tags can be used inside of Apple Photos for various tasks, most importantly to create Smart Albums that key off one or more of them.

Copyright information

As you will capture more and more media with multiple GoPro cameras, it is always a good idea to set the Artist/Author/Copyright fields in Exif. That way you keep a record of the files you have created.

A Simple workflow

All of this needs to be part of a simple workflow that captures and stores the original media as well as the processed files. GoProX will most likely only be one step in your process and as been designed to recursively walk the source tree and process all media files in its structure. It does not matter if the source images are in a single folder or organized by date, camera or whatever subject you choose.

On the output side, a very simple data-based file structure is created with one folder per original media creation date.

The tool can be run on a single subfolder of your source files or at the root of it. The output will always be the date folder hierarchy at the destination folder.

When re-run, existing target files are skipped but logged in the error log. That way large or incremental processing jobs can be restarted as often as you like. This comes with some processing overhead for existing files but is generally very fast.

If you want to reprocess certain files, simply delete them at the destination folder and rerun the process.

Storage hierarchy

goprox is based on a simple file-based library structure for arching, importing, and processing media files over time. By default, it creates the following structure on disk:

goprox/ (named and placed as required)
├── archive/
├── imported/
├── processed/
└── deleted/

Any of these first-level storage subtrees can be kept as directories or replaced by links to different storage devices. This helps distribute storage requirements across multiple devices but can be equally beneficial for processing performance.

The following example keeps archive and deleted on the main drive while pointing imported and processed to different locations.

goprox/ (named and placed as required)
├── archive/
├── imported -> /Volumes/Office G-RAID/goprox/imported/
├── processed -> /Volumes/Office G-RAID/goprox/processed/
└── deleted/

To create this distributed structure, simply create another goprox library skeleton on any storage device of your choice (in this case /Volumes/Office G-RAID/) (only the portions of the structure you want to link to are required). For example:

/Volumes/Office G-RAID/goprox/ 
├── imported
├── processed

You could also consider putting archive on a dedicated low-cost storage device:

/Volumes/Office Dock/goprox/ 
├── archive

Once created, head over to the main library, remove the empty directories (if you are performing this as a migration see below) you would like to point to different locations, and simple run:

ln -s /Volumes/Office\ G-RAID/goprox/imported/ imported
ln -s /Volumes/Office\ G-RAID/goprox/processed/ processed

Once set up as required, goprox will be fully aware of the distributed nature of the library and will validate the structure every time you run it. As part of the validation, it will check and warn of broken links and, if necessary, stop the execution of operations that would require the portions of the library that are unreachable.

This is necessary to avoid situations where external storage devices are not mounted or simply not available when on the road.

Simple run goprox --verbose with no other parameters to get the storage validation summary:

...
Info: Validating storage hierarchy... 
Info: goprox library: /Users/xxxxxxx/goprox directory validated 
Info: goprox archive: /Users/xxxxxxx/goprox/archive directory validated 
Warning: goprox imported: /Users/xxxxxxx/goprox/imported is a broken link to /Volumes/Office G-RAID/goprox/imported/
Warning: Make sure the storage device is mounted and the directory has not been moved. 
Warning: goprox processed: /Users/xxxxxxx/goprox/processed is a broken link to /Volumes/Office G-RAID/goprox/processed/ 
Warning: Make sure the storage device is mounted and the directory has not been moved. 
Info: goprox deleted: /Users/xxxxxxx/goprox/deleted directory validated 
Info: Finished storage hierarchy validation. 
Info: GoProx processing finished. 

In this particular example, you can still perform --archive, --firmware, or --clean tasks but will see an error if you attempt --import or --process.

Inside the library

Once you get started, you will see goprox fill the library's content with your GoPro media data.

Here is a sample summary of how goprox builds the tree inside the various components:

goprox/
├── archive/
│   ├── 20221015125658_GoPro_Hero10_8034.tar.gz
│   ├── 20221015131037_GoPro Max_6013.tar.gz
│   ├── 20221015103421_GoPro_Hero11_4632.tar.gz
│   └── 20220713183316_GoPro_Hero9_0021.tar.gz
├── imported/
│   ├── 2021
│   └── 2022
│       ├── 20220520
│       └── 20221013
│           ├── 20221013084759_GoPro_Hero11_5131_G0294305.JPG
│           ├── 20221013094220_GoPro_Hero10_4299_G0019484.JPG
│           ├── 20221013153428_GoPro_Max_6013_GS016167.360
│           └── geonames.json
└── processed/
    ├── JPEG
    │   ├── 2021
    │   └── 2022
    │       ├── 20220520
    │       └── 20221013
    │           ├── P_20221013084759_GoPro_Hero11_5131_G0294305.JPG
    │           └── P_20221013094220_GoPro_Hero10_4299_G0019484.JPG
    ├── MP4
    └── 360
        ├── 2021
        └── 2022
            ├── 20220520
            └── 20221013
                └── P_20221013153428_GoPro_Max_6013_GS016167.360

archive is a flat directory with the individual sdcard image backups as tar.gz. These archives usually get migrated to long term storage (eg: AWS Glacier) or simply deleted after a while. When you get started with goprox, it is strongly recommended to perform archives as they are a simple, foolproof way to undo anything that could go wrong as you experiment with features and your workflow. goprox supports imports straight from an archive file. This allows you to rerun any process from scratch without ever losing any data. The cost is an extra copy of all the media.

imported contains a structure by year and then by date to keep the hierarchy manageable. Within a particular day, you will find all media goprox has imported. These dates are derived from when the media was created/shot and NOT when it was imported. That information you can find in the modification dates of each file. goprox has a strict DO-NOT-OVERRIDE existing files policy. It only adds, never replaces. If you want to rerun a particular day, delete those files within the tree and re-run the import from your archives. Be aware that the archive dates do not necessarily correspond with the individual file date. The archives are labeled by the day and time the archive has been created. All media files inside of imported are unmodified but renamed. It is the exact media that came off your sdcard but intelligently named according to the files EXIF data.

processed contains a further refined structure by file type, then year and date. This is done because, in many cases, JPEG, MP4, and 360 files go through different workflows in post-production. For example, JPEGs might get imported into Apple Photos, whereas MP4s get used by Blackmagic DaVinci or similar. 360s usually have to be processed by GoPro Player first before they can be used in cutting and editing. processed media files are rewritten with additional metadata that allows Apps to search, sort, and filter these files in new ways. To be able to distinguish imported from processed media, a P_ prefix is added to all processed media.

deleted is currently a placeholder for future functionality to allow upstream deletion propagation back into the goprox library. It will contain lists of files that have been deleted in upstream Apps like Apple Photos to remove those files retroactively from the goprox library.

Performance considerations

For extra performance, you could consider placing imported and processed on different SSDs. Internal NVME drives can get up to 1.3GB/s transfer rates, while external devices like Samsung's T7s max out at 600-700MB/s. The G-Raid can do about 400MB/s in RAID 0 and 200MB/s in RAID 1.

Existing file migration

If you need to migrate file structures from one device to another, it is highly recommended to bypass Finder and use cp in archive mode to maximize copy performance but also preserve owner, date & time as well as other attributes in your library.

cp -RpPvn source target

cp -RpPvn /Volumes/Original/goprox/imported /Volumes/Office\ G-RAID/goprox

This will safely copy all the contents of the source to the new target. It will skip existing files (so you can re-run it in case of a failure) but it is important to capture and review its output, particularly the error out. For long-running migrations wrap in nohup:

nohup cp -RpPvn source target 1>>cp-progress.log 2>>cp-errors.log

nohup cp -RpPvn /Volumes/Original/goprox/imported /Volumes/Office\ G-RAID/goprox 1>>goprox-cp-progress.log 2>>goprox-cp-errors.log 

Supported GoPro Models

goprox is actively being developed and tested with the following cameras:

  • GoPro Hero 8 (HD8.01.02.51.00)
  • GoPro Hero 9 (HD9.01.01.72.00)
  • GoPro Hero 10 (H21.01.01.46.00)
  • GoPro Hero 11 (H22.01.01.10.00)
  • GoPro Max (H19.03.02.00.00)
  • GoPro The Remote (GP.REMOTE.FW.01.02.00)

Most functionality should work with older GoPro models as well, just the --firmware and --firmware labs options are limited to these models.

Performance

The exiftool has phenomenal capabilities and if you let it do the vast majority of work by itself, it is really fast.

Testing on 20,000 images on a 2017 iMac with a quad-core i5 and one 2TB SSD (source: original files folder) plus one 14TB HDD (target: processed files folder) have continuously resulted in 200MB+/sec read and write speeds at less than 20% CPU utilization.

Simplicity

I tried to keep the tool as simple as possible. This undoubtedly will come with limitations for certain use-cases. Feel free to drop me a line or a PR with enhancements.

Credits & Disclaimers

GoProX is not related to GoPro Inc or its products. It is not supported nor endorsed by GoPro Inc. GoProX is not related to Apple Inc, Blackmagic Design Pty Ltd or any other products or platforms referred to as part of the description or documentation of the tool unless explicitly stated.

GoProX leverages the exiftool by Phil Harvey to extract common GoPro metadata to name and tag images and videos for further processing.

GoProX leverages the GeoNames database by Marc Wick to perform GPS-based geocode lookups of timezones and related data.

Portions of code and documentation created with the help of ChatGPT.

Links & Resources

Homebrew tap to enable the installation of goprox: homebrew-fxstein

goprox's People

Contributors

fxstein avatar inode64 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

goprox's Issues

Bug: Incorrect file creation dates

Both import and process seem to be setting the incorrect FileCreateDate. Imported and processed files get the date the process was run and not that of the original image creation date.

Needs further analysis.

Documentation: Update ReadMe with latest features and updates

Update README.md to reflect the recent changes from:

  • #12 Feature: Test Storage Hierarchy before Operations
  • #14 Feature: Import from Archive
  • #19 Feature: exiftool error handling

In addition, correct the 360 file handling description that states incorrectly that 360 files become mp4 files after processing. This was an earlier attempt that turned out to be an unworkable solution.

Feature: AWS Glacier support

In addition to #10 add the ability to archive off no longer actively used media files to AWS S3 Glacier storage leveraging the AWS CLI

brew install awscli
aws glacier help

Feature: Add basic support for DJI drone import

Enable the import from DJI drone sd-cards similar to the GoPro media.

Since there is no version text file on the sd-cards of DJI drones, it requires some directory/filename logic to identify as a DJI drone.

Won't be able to recognize the drone type or serial number, but at least the fact that it is DJI drone media.

➜  tree -d
.
├── DCIM
│   └── 100MEDIA
├── LOST.DIR
└── MISC
    ├── GIS
    ├── IDX
    └── THM
        └── 100

9 directories
➜  MISC tree   
.
├── GIS
│   └── dji.gis
├── IDX
├── IDX_BLOCK
└── THM
    └── 100
        ├── DJI_0001.SCR
        ├── DJI_0001.THM
        ├── DJI_0002.SCR
        ├── ...
        ├── DJI_0524.THM
        ├── DJI_0525.SCR
        └── DJI_0525.THM

Bug: Make test option local timezone independent

Turns out the file creation time for files without valid EXIF data (NODATA) changes dependent on in which timezone the developer machine is setup in. As such the file names change and the test fails.

[2022-12-18 10:14:47] Error: Test failed! 
[2022-12-18 10:14:47] 
[2022-12-18 10:14:48]  .../2022/20220214/20220214204307_NODATA_GH010739.MP4 | Bin 597806 -> 0 bytes
[2022-12-18 10:14:48]  .../2022/20220214/20220214204307_NODATA_GX010093.MP4 | Bin 14966973 -> 0 bytes
[2022-12-18 10:14:48]  ...20306001216_NODATA_IMG_20220306_001216_00_004.dng | Bin 18535575 -> 0 bytes
[2022-12-18 10:14:48]  ...20306001216_NODATA_IMG_20220306_001216_00_004.dng | Bin 18539894 -> 0 bytes
[2022-12-18 10:14:48]  .../20220214/P_20220214204307_NODATA_GH010739.mp4    | Bin 601364 -> 0 bytes
[2022-12-18 10:14:48]  .../20220214/P_20220214204307_NODATA_GX010093.mp4    | Bin 14970530 -> 0 bytes
[2022-12-18 10:14:48]  6 files changed, 0 insertions(+), 0 deletions(-)

Feature: Support Windows platform

Currently goprox is only being developed and tested under MacOS. With the support of zsh in Windows 10, the same workflow should be easily possible under Windows.

Looking for help from someone with Windows experience and the ability to test.

Feature: exiftool error handling

Need to implement an exiftool error handling strategy. While some errors like skipping existing files are ok in most cases, other errors are not. This applies to all calls of the exiftool but specifically where followup actions like --clean depend on the successful completion of a prior exiftool step.

This was raised by @Giga in #18. At the minimum we need to capture the exit status of every exiftool run and make it available as part of other logic for decision of whether to proceed in the goprox logic or not.

Bug: Allow cleanup with import and without archive

Contrary to the readme, cleanup is only allowed when archiving.

Archiving and importing everything is taking a lot of space.

It would be great if cleanup was allowed for import only as well. Maybe with an additional option if import is considered dangerous and could damage file?

Feature: Delta patch compress optional files

The storage requirements for goprox are very significant when all layers of the library are being kept for future re-prosessing.

There are basically 3 copies of data: archive, imported and processed

Both archive and imported are optional lineage copies that allow a user to go back to the originals coming off a camera and re-process the entire workflow. With early versions of goprox this is desirable as logic changes and even bugfixes can easily be applied to the original media.

Since the delta between imported and processed media is metadata only - we are not resampling or recompressing the media files - delta patches could be leveraged to replace media file with significantly smaller delta files, while allowing to restore the original file later on.

Initial testing has resulted in a 99% reduction in storage required to hold imported delta patch files, compared to the original media files.

Example:

xdelta3 -S djw -s /Users/oratzes/goprox-test-moved/imported/2022/20221011/20221011151401_GoPro_Hero10_2442_G1541642.JPG /Users/oratzes/goprox-test-moved/processed/JPEG/2022/20221011/P_20221011151401_GoPro_Hero10_2442_G1541642.jpg P_20221011151401_GoPro_Hero10_2442_G1541642.xdelta

produces a 1.4kB delta file compared to the original 4.7MB image. This would allow users to keep the entire imported media path while consuming 99% less storage than a full copy of the data.

goprox needs to be able to generate the delta patch files, replace the original files in imported and restore them on demand as needed for future processing.

Feature: Create hidden markers on GoPro cards

Create and leave hidden markers on GoPro media cards once various goprox processes have been completed successfully.

For example:

.goprox.archived
.goprox.imported
.goprox.cleaned
.goprox.fwchecked

This enables a quick and easy way to check if and when goprox has performed certain functions against the media cards. The timestamp represents the time the process was last successfully completed.

Test and verify new exiftool version 12.50

The new production release 12.50 just became available through home-brew. Initial testing reveals some minor changes in processed files output. Need to verify and make sure nothing broke.

Feature: Test Storage Hierarchy before Operations

Make sure to test the availability of all storage components - especially links - before executing any operations. In complex storage environments where the library components are distributed over multiple volumes or disks, a missing volume will create runtime errors that might get caught too late.
Important to check for key folder availability before engaging in any operation that copies, moves or writes media files.

Feature: GPSTime

Implement gpstime feature to allow the use of the GPS timestamp plus the timezone information from the geonames feature for timestamping of the processed media files. This would enable the use of the GPS time information for timecode synchronization of multiple camera angles in apps like DaVinci Resolve.

Consider adding an additional prefix to the processed files to clearly identify GPS timed media files.

References

This would be similar to the GoPro Labs GPS timecode implementation inside the camera firmware but with the big difference that goprox is timezone aware and as such can correctly set the entire timestamp and not just minutes and seconds - which is problematic at hour and day boundaries.
https://gopro.github.io/labs/control/gpssync/

Bug: Permission Denied during --firmware processing

As of Ventura 13.4 and Homebrew 4.0.22-6-gf71294d getting the following permissions error when performing --firmware task:

➜  goprox --version
goprox v00.52.00
➜  goprox --firmware labs 
GoProX started... 
Checking firmware... 
_firmware:34: permission denied: /opt/homebrew/Cellar/goprox/00.52.00/bin/firmware.labs/HERO11 Black/H22.01.02.10.70
No firmware files found at /opt/homebrew/Cellar/goprox/00.52.00/bin/firmware.labs/HERO11 Black
GoProX processing finished. 

same with

➜  sudo goprox --firmware labs 
GoProX started... 
Checking firmware... 
_firmware:34: permission denied: /opt/homebrew/Cellar/goprox/00.52.00/bin/firmware.labs/HERO11 Black/H22.01.02.10.70
No firmware files found at /opt/homebrew/Cellar/goprox/00.52.00/bin/firmware.labs/HERO11 Black
GoProX processing finished. 

Feature: Import from Archive

Imports and archives are normally performed directly from the root of the GoPro sdcard. In some cases, it is required to import an archive instead. This is especially helpful when mobile collection is limited to creating archives and further processing is then performed at home or in the office.

goprox creates archives like:

20220930092409_GoPro_Hero10_2442.tar.gz
20220930093920_GoPro_Hero10_8034.tar.gz
20220930103800_GoPro Max_6013.tar.gz
20220930103807_GoPro_Hero11_8909.tar.gz
20220930103816_GoPro_Hero11_5131.tar.gz

Currently, an archive needs to be uncompressed into a directory and then goprox can import from there.
If the source is an archive file *.tar.gz the import process should happen automatically without the need for a manual decompression step.

Feature: Enhance system level logging

Integrated goprox logging with macOS system logs leveraging logger. This is required to support the auto mount feature running goprox in the background whenever a new mount point is being created.

Feature: Propagate and Collect Deletes

Imported and processed files of goprox are mainly imported into other image and video processing platforms. For images, a common path is to import all processed files into Apple Photos. This allows for easy browsing, filtering, and sorting (based on goprox metadata and tags). Once imported it is very common to review the images for favorites, decent shots as well as outright junk. Often bad images get deleted quickly from Photos to reduce the amount of overhead to photo libraries.

Once deleted - sometimes as much as 80-90% of imported images, the problem becomes that the goprox library continues to hold the deleted images and future imports create the problem of re-importing previously deleted images, especially after 30-40 days when the deleted items list in Photos gets purged.

However it is this list of deleted items, that is programmatically available via Photos internal SQLite database for said 30-40 days. As such it would be easy to extract the list of deleted images and media files from photos, apply some filters and in return remove them from the processed or even imported library paths. The originals would still be available in the original SDcard images if there is ever a need to recover a deleted file.

In order to make this permanent, goprox will need to keep an ever-growing list of deleted media files and eliminate them from future processing as well as from the current library storage.

The Photos SQLite store is commonly found here:

~/Pictures/Photos\ Library.photoslibrary/database/Photos.sqlite

The query to extract recently deleted media files from Photos would be like this:

SELECT 
  zAddAssetAttr.ZORIGINALFILENAME AS 'zAddAssetAttr-Original Filename'
FROM ZASSET zAsset
  JOIN ZADDITIONALASSETATTRIBUTES zAddAssetAttr ON zAddAssetAttr.Z_PK = zAsset.ZADDITIONALATTRIBUTES
WHERE zAsset.ZTRASHEDSTATE = 1
ORDER BY zAddAssetAttr.ZORIGINALFILENAME;

and results in something like this:

IMG_0922.PNG
P_20220923092015_GoPro_Max_6013_GS__4797.jpg
P_20220923092019_GoPro_Max_6013_GS__4798.jpg
P_20220923092026_GoPro_Hero11_8909_GOPR0089.jpg
P_20220923092030_GoPro_Hero11_8909_GOPR0090.jpg
P_20220923092033_GoPro_Hero11_5131_GOPR0100.jpg
P_20220923092037_GoPro_Hero11_5131_GOPR0101.jpg
P_20220923125107_GoPro_Max_6013_GS__4802.jpg
P_20220923125118_GoPro_Hero11_4632_GOPR0075.jpg
P_20220923125120_GoPro_Hero11_8909_GOPR0094.jpg
P_20220923125127_GoPro_Hero11_5131_GOPR0105.jpg
P_20220923125157_GoPro_Max_6013_GS__4803.jpg
P_20220923125209_GoPro_Hero11_4632_GOPR0076.jpg
P_20220923125210_GoPro_Hero11_8909_GOPR0095.jpg
P_20220923125217_GoPro_Hero11_5131_GOPR0106.jpg

It contains any recently deleted media files and would need to be filtered for goprox specific files.

To store the list of deleted files a new deleted substructure would need to be introduced as part of the library. Deleted images could be grouped into list files by year for ease of processing.

Workflow: Implement git-flow Model

As the project attracts additional collaborators it will become necessary to implement a more formal contribution model and migrate away from the quick and dirty everything-happens-in-main model.

We will be implementing the git-flow model as described here: github-flow

Bug: Fix firmware processing

Fix a few issues with firmware processing:

  • Cope with situations where no firmware files are available without breaking the logic
  • Fix path to /MISC/version.txt when firmware check does not run against the current directory

Misc: Create FreeBSD Port

I wanted to run this within a FreeBSD jail to reorganize a bunch of media already on a TrueNAS appliance.

Since macOS and *BSD share some heritage this was actually much easier than I thought it would be.

# $FreeBSD$

PORTNAME=	goprox
DISTVERSION=	00.52.00
CATEGORIES=	multimedia

DISTVERSIONPREFIX=	v

MAINTAINER=	[email protected]
COMMENT=	Missing GoPro workflow manager for zsh
WWW=		https://github.com/fxstein/GoProX

LICENSE=	MIT

RUN_DEPENDS=	exiftool:graphics/p5-Image-ExifTool \
		jq:textproc/jq \
		zsh:shells/zsh

USES=		shebangfix

USE_GITHUB=	yes
GH_ACCOUNT=	fxstein
GH_PROJECT=	GoProX

SHEBANG_LANG=	zsh
SHEBANG_FILES=	goprox

zsh_OLD_CMD=	"/usr/bin/env zsh" /bin/zsh /usr/bin/zsh
zsh_CMD=	${LOCALBASE}/bin/zsh

NO_BUILD=	yes
DOCS=		README.md LICENSE

do-install:
	${MKDIR} ${STAGEDIR}${DATADIR}
	${INSTALL_SCRIPT} ${WRKSRC}/goprox ${STAGEDIR}${DATADIR}/goprox
	${LN} -fs ${DATADIR}/goprox ${STAGEDIR}${PREFIX}/bin/goprox
	${INSTALL_MAN} ${WRKSRC}/man/goprox.1 ${STAGEDIR}${PREFIX}/man/man1/
	# NOTE: Firmware isn't included to keep the package size low.
	#${MKDIR} ${STAGEDIR}${DATADIR}/firmware
	#(cd ${WRKSRC}/firmware && ${COPYTREE_SHARE} . ${STAGEDIR}${DATADIR}/firmware)
	#${MKDIR} ${STAGEDIR}${DATADIR}/firmware.labs
	#(cd ${WRKSRC}/firmware.labs && ${COPYTREE_SHARE} . ${STAGEDIR}${DATADIR}/firmware.labs)

.include <bsd.port.mk>

I have some remaining questions:

  • The source archive is nearing 1GB: could firmware be downloaded on demand instead?
  • Is this useful enough to submit to the FreeBSD ports tree?

Feature: Downsample videos

Create the ability to downscale and sample video files. Create lower resolution and time limited previews that are significantly smaller in size and can be easier shared with various applications and platforms.

Leverage ffmpeg to downscale videos to e.g. 720p, lower frame rates and quality and limit to the first 30 sec of any video. Place preview samples in dedicated preview folder structure.

Feature: Timeshift

Implement time shift feature to modify the time when a media file has been created.

This could be implemented based on GPS time and timezone see geonames feature or by time offset.

Need to determine how to best select the media files that should be shifted and how to persist that time shift across multiple goprox runs.

References

Feature: Enhanced logging

Add the ability to make logging configurable and apply to exiftool output dynamically.

Leverage -v and -q options to increase or decrease exiftool output in line with the overall logging level for goprox

Feature: Improved testing

  • Add archive processing to testing
  • Add additional GoPro metadata to originals directory
  • Exclude various markers and files from test repo tree

Feature: Improved archive processing

Refactor goprox --archive processing to read the camera model and serial number from /MISC/version.txt rather than the first media file encountered. This creates a more consistent behavior and avoids empty archive file names in case no matching media file can be found.

Also, exclude newly created hidden .goprox markers from the archive.

Feature: Multi Tier Storage Support

Currently goprox only supports a single storage hierarchy even though portions of the library can be distributed across multiple storage volumes by leveraging links for subfolders of it. For example imported can be located on one dedicated SSD while processed can be located on another SSD and archive can be mapped to an internal drive. Distributing the media file structure can help with growing libraries and leverage the full throughput of current MacBooks or similar.

However, in cases where processing is performed in multiple physical locations - for example, mobile - on-the-road capture and import vs home/office post-processing a more complex storage hierarchy might be required.

While out on set or on the road, capture from SD cards needs to happen rapidly and often involves minimal infrastructure, commonly with external HDD or SSD devices.
When back in the production studio or office, additional storage devices with much larger capacities are often used to collect all the media files for an entire or even multiple projects.

Currently, the workflow is rather manual and requires goprox configurations that are different from field/road to office/home which in turn requires manual copying and transferring of media.

Proposed solution

Add the principle of mobile vs home configuration setups to goprox and select the environment at runtime or potentially even autodetect the environment based on the availability of certain storage devices connected to the computer.
In Mobile mode archive/import and optionally process media data into staging devices eg external SSDs connected to the laptop.
Once back in the office/home migrated these staged media files into the permanent storage hierarchies.

Related

In addition, expand this capability through the support of AWS S3 Glacier storage #11 for long term archival of no longer actively required media files

Feature: Single file summary

Create the ability to pass a single image file to goprox (even without the path) and provide the full path and summary metadata together with warnings if e.g. system create date is not matching the EXIF create date.

goprox 20221028112412_GoPro_Hero11_5131_G0327016.JPG

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.