Metadata-Version: 2.4
Name: gopro-merger
Version: 0.1.3
Summary: A Python tool that automatically groups, combines, and compresses GoPro video chapters using FFmpeg.
Author: Nida Anis
License-Expression: MIT
Project-URL: Homepage, https://github.com/N21A/gopro-merger
Project-URL: Issues, https://github.com/N21A/gopro-merger/issues
Keywords: gopro,ffmpeg,video,hevc,video-compression
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# gopro-merger

`gopro-merger` is a command-line tool for automatically grouping, merging, and compressing chaptered GoPro recordings with FFmpeg.

It recognises common GoPro filename formats, combines each recording in chapter order, and encodes the result as HEVC/H.265 to reduce storage use.

> The current release has primarily been tested on Windows. It is designed to run on Windows, macOS, and Linux.

## Features

- Detects newer GoPro chapter names such as `GX010021.MP4`, `GX020021.MP4`, and later chapters.
- Supports older `GOPR1234.MP4` and `GP011234.MP4` naming.
- Groups separate recordings automatically.
- Merges each recording into one continuous MP4.
- Compresses video to HEVC/H.265.
- Uses NVIDIA NVENC when available.
- Uses CUDA/NVDEC hardware decoding when supported, keeping decoded frames on the GPU for faster end-to-end transcoding.
- Falls back automatically to NVENC with software decoding, then CPU encoding with `libx265`.
- Provides `quality`, `balanced`, `fast`, and `maximum` speed profiles.
- Uses the `balanced` profile by default for faster processing with sensible compression efficiency.
- Copies audio and GoPro telemetry/data streams where supported.
- Removes `.LRV` and `.THM` sidecar files after successful processing.
- Keeps original MP4 files by default.
- Validates output video streams and duration with `ffprobe` before treating an encode as successful.
- Shows source size, output size, and the achieved storage reduction.
- Can permanently delete successfully processed and validated source MP4 files after explicit confirmation.
- Opens a graphical folder picker when run without a folder argument and Tkinter is available.
- Requires no third-party Python packages at runtime.

## Requirements

### Required

- Python 3.9 or newer.
- FFmpeg installed and available on your system `PATH`.

Check that FFmpeg is available:

```bash
ffmpeg -version
```

### Optional

- **Tkinter** for the graphical folder picker.
  - Availability depends on how Python was installed.
  - If Tkinter is unavailable, pass the source directory as a command-line argument.
- **NVIDIA GPU and compatible drivers** for hardware-accelerated HEVC encoding with `hevc_nvenc`.
  - If NVENC is unavailable or fails in automatic mode, `gopro-merger` falls back to `libx265`.

## Install FFmpeg

FFmpeg is an external application and is not installed automatically with `gopro-merger`.

### Windows

Using `winget`:

```powershell
winget install Gyan.FFmpeg
```

Or using Chocolatey:

```powershell
choco install ffmpeg
```

Close and reopen your terminal after installation, then verify:

```powershell
ffmpeg -version
```

### macOS

Using Homebrew:

```bash
brew install ffmpeg
```

Verify:

```bash
ffmpeg -version
```

### Linux

Install FFmpeg using your distribution's package manager.

Ubuntu or Debian:

```bash
sudo apt update
sudo apt install ffmpeg
```

Arch Linux:

```bash
sudo pacman -S ffmpeg
```

Fedora:

```bash
sudo dnf install ffmpeg
```

FFmpeg availability may depend on which software repositories are enabled on your distribution.

## Install gopro-merger

### Recommended: pipx

[pipx](https://pipx.pypa.io/) installs command-line applications in isolated Python environments while making their commands available system-wide.

Once `gopro-merger` is published on PyPI:

```bash
pipx install gopro-merger
```

Then verify the installation:

```bash
gopro-merger --help
```

#### Install pipx on Windows

```powershell
py -m pip install --user pipx
py -m pipx ensurepath
```

Close and reopen PowerShell after running `ensurepath`, then install:

```powershell
pipx install gopro-merger
```

#### Install pipx on macOS

Using Homebrew:

```bash
brew install pipx
pipx ensurepath
pipx install gopro-merger
```

Open a new terminal after running `ensurepath` if the `pipx` command is not immediately available.

#### Install pipx on Linux

Use your distribution's package manager where available.

Ubuntu or Debian:

```bash
sudo apt install pipx
pipx ensurepath
pipx install gopro-merger
```

Alternatively:

```bash
python3 -m pip install --user pipx
python3 -m pipx ensurepath
```

Open a new terminal after running `ensurepath`.

### Alternative: pip

You can install the package into an existing Python environment:

```bash
python -m pip install gopro-merger
```

On macOS or Linux, the command may be:

```bash
python3 -m pip install gopro-merger
```

For a standalone command-line application, `pipx` is generally preferable because it avoids modifying your main Python environment.

## Usage

Open the graphical folder picker:

```bash
gopro-merger
```

Process a specific folder on Windows:

```powershell
gopro-merger "D:\GoPro\D2S1"
```

Process a specific directory on macOS or Linux:

```bash
gopro-merger "/path/to/GoPro/D2S1"
```

Outputs are written to a `processed` directory inside the selected source directory.
When a resolution preset is selected, the output filename includes it, for example `GX0021_merged_hevc_1080p.mp4`.

## Options

| Option | Description |
|---|---|
| `--quality 18-35` | Set HEVC quality. Lower values produce better quality and larger files. Default: `26`. |
| `--resolution original` | Keep the source resolution. This is the default. |
| `--resolution 2160p` | Scale to 2160 pixels high while preserving aspect ratio. |
| `--resolution 1440p` | Scale to 1440 pixels high while preserving aspect ratio. |
| `--resolution 1080p` | Scale to 1080 pixels high while preserving aspect ratio. |
| `--resolution 720p` | Scale to 720 pixels high while preserving aspect ratio. |
| `--speed quality` | Use slower settings for better compression efficiency. |
| `--speed balanced` | Use a faster balanced NVENC/CPU profile. This is the default. |
| `--speed fast` | Prioritise encoding speed while retaining reasonable compression. |
| `--speed maximum` | Use the fastest settings, with reduced compression efficiency. |
| `--encoder auto` | Use NVENC when available and fall back to CPU encoding. This is the default. |
| `--encoder nvenc` | Require NVIDIA NVENC hardware encoding. |
| `--encoder cpu` | Force CPU encoding with `libx265`. |
| `--no-hw-decode` | Disable CUDA/NVDEC decoding while still allowing NVENC encoding. |
| `--combine-all` | Combine every MP4 in the source directory into one output. |
| `--keep-sidecars` | Keep `.LRV` and `.THM` sidecar files. |
| `--overwrite` | Overwrite an existing output file. |
| `--delete-originals` | Offer to permanently delete successfully processed source MP4 files after confirmation. |
| `--version` | Display the installed version. |
| `--help` | Display the command-line help. |

## Examples

Choose a higher-quality encode:

```bash
gopro-merger "/path/to/GoPro/D2S1" --quality 24
```

Downscale 4K footage to 1080p for a substantially smaller output:

```bash
gopro-merger "/path/to/GoPro/D2S1" --resolution 1080p --quality 26
```

For smaller archival files with stronger compression:

```bash
gopro-merger "/path/to/GoPro/D2S1" --resolution 1080p --quality 29 --speed quality
```

Use the faster profile:

```bash
gopro-merger "/path/to/GoPro/D2S1" --speed fast
```

Use the maximum-speed profile:

```bash
gopro-merger "/path/to/GoPro/D2S1" --speed maximum
```

Force NVIDIA encoding:

```bash
gopro-merger "/path/to/GoPro/D2S1" --encoder nvenc
```

Force CPU encoding:

```bash
gopro-merger "/path/to/GoPro/D2S1" --encoder cpu
```

Disable hardware decoding while retaining NVENC encoding:

```bash
gopro-merger "/path/to/GoPro/D2S1" --no-hw-decode
```

Keep `.LRV` and `.THM` files:

```bash
gopro-merger "/path/to/GoPro/D2S1" --keep-sidecars
```

Combine every MP4 in the directory into one output:

```bash
gopro-merger "/path/to/GoPro/D2S1" --combine-all
```

Use `--combine-all` only when the files belong together and use compatible stream formats.

Overwrite an existing output:

```bash
gopro-merger "/path/to/GoPro/D2S1" --overwrite
```

Delete original MP4 files after successful processing:

```bash
gopro-merger "/path/to/GoPro/D2S1" --delete-originals
```

The program lists every eligible source file, shows their combined size, and requires you to type `DELETE` exactly before anything is removed.

## Safety

Original MP4 files are kept unless `--delete-originals` is supplied.

When `--delete-originals` is used:

- deletion only occurs after FFmpeg successfully creates an output that passes validation;
- validation checks that the output contains video and that its duration matches the source sequence within a small tolerance;
- only files successfully processed and validated during the current run are eligible;
- source files belonging to failed recordings are kept;
- source files belonging to outputs skipped because they already existed are kept;
- the program displays the eligible files and their combined size;
- you must type `DELETE` exactly to confirm;
- deleted files are permanently removed rather than moved to the Recycle Bin or Trash.

Check each merged output before confirming deletion of important source footage.

## GoPro filename grouping

Newer naming format:

```text
GX010021.MP4
GX020021.MP4
GX030021.MP4
```

These files are grouped as chapters of the same recording and merged in chapter order.

Older naming format:

```text
GOPR1234.MP4
GP011234.MP4
GP021234.MP4
```

These files are also grouped and merged in chapter order.

If no recognised GoPro naming pattern is found, the program treats the MP4 files in the directory as one filename-sorted sequence.

## Running from source

Clone or download the repository, then run the script directly.

Windows:

```powershell
py gopro_merger.py "D:\GoPro\D2S1"
```

macOS or Linux:

```bash
python3 gopro_merger.py "/path/to/GoPro/D2S1"
```

To install your local checkout as a command-line application:

```bash
pipx install .
```

For an editable development installation:

```bash
python -m pip install -e .
```

## Updating and uninstalling

Upgrade a PyPI installation:

```bash
pipx upgrade gopro-merger
```

Uninstall:

```bash
pipx uninstall gopro-merger
```

## Notes

- HEVC/H.265 compression is lossy.
- The default `balanced` profile uses faster NVENC settings than the original p5 multipass configuration.
- The `quality` profile is slower but normally provides better compression efficiency.
- The `maximum` profile is fastest but can produce larger files or lower quality at the same quality value.
- CPU encoding with `libx265` is normally slower than NVIDIA NVENC.
- HEVC playback support varies by operating system, application, and installed codecs.
- GoPro telemetry preservation depends on the streams present in the source files and support in the installed FFmpeg build.
- FFmpeg concat processing expects compatible stream layouts across files being merged.

## License

This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
