Manatee

GoPro chapters: why one recording arrives as GX01, GX02, GX03

You record one continuous twenty-minute take. You copy the card to the Mac and find three or four files: GX010042.MP4, GX020042.MP4, GX030042.MP4. Each plays, each stops abruptly, and together they are the take.

This is chaptering, and it is deliberate. Knowing why it happens tells you how to rejoin the pieces without re-encoding them.

Why cameras split long recordings

The file system on the memory card is the reason. Cards are commonly formatted exFAT or, on older or smaller cards, FAT32. FAT32 cannot store a file larger than 4 GB, full stop.

Rather than stopping the recording when it reaches that ceiling, action cameras close the current file and immediately open the next, losing at most a frame at the boundary. The result is a set of chapters that play back as a continuous take when the camera’s own software reassembles them.

The naming encodes the relationship. In GX010042.MP4, the GX is the codec marker, 01 is the chapter number, and 0042 is the recording number. So GX010042, GX020042 and GX030042 are chapters one, two and three of recording forty-two. Files with different trailing numbers are different takes, however close together they were recorded.

Sorting by name in the Finder does not group them usefully, because the chapter number comes before the recording number. Sorting by date created is more reliable.

Why you cannot just concatenate them

The instinct is to append the files end to end, and it does not work. cat a.mp4 b.mp4 > joined.mp4 produces a file that is the right size and will not play.

The reason is structural. An MP4 is not a stream of frames; it is a container with a header block, a data block, and an index block that maps playback time to byte positions. Inspecting a real file shows the layout:

ftyp (32 bytes) → free (8 bytes) → mdat (23,481,548 bytes) → moov (33,133 bytes)

Append two of those and you get two headers, two data blocks and two indexes, with the second index describing positions that are now wrong. Players read the first header, find an index that stops partway, and give up.

Joining MP4 files properly means rewriting the container so there is one header, one continuous data block and one index covering the whole thing.

Joining without re-encoding

Because every chapter came from the same camera in the same recording, the streams are identical in codec, resolution and frame rate. That means they can be joined without decoding anything, which is fast and lossless.

Make a list file naming the chapters in order:

cd /path/to/footage
printf "file '%s'\n" GX010042.MP4 GX020042.MP4 GX030042.MP4 > chapters.txt

Check the file before using it, since order is everything:

cat chapters.txt

Then join:

ffmpeg -f concat -safe 0 -i chapters.txt -c copy joined.mp4

-c copy is what makes this lossless: the audio and video streams are moved into the new container untouched, so the output is bit-for-bit the same picture as the chapters. A twenty-minute take joins in seconds rather than the minutes a re-encode would take, and no quality is lost.

To build the list automatically for a recording, matching on the trailing number:

printf "file '%s'\n" $(ls GX*0042.MP4 | sort -t X -k2) > chapters.txt

Always read the resulting chapters.txt before running the join. A wrong order produces a video that jumps, and the failure is not obvious until you watch it.

Verifying the join

Compare the total duration of the parts against the result:

for f in GX0*0042.MP4; do
  ffprobe -v error -show_entries format=duration -of csv=p=0 "$f"
done | paste -sd+ - | bc

ffprobe -v error -show_entries format=duration -of csv=p=0 joined.mp4

The two figures should agree to within a fraction of a second. A large discrepancy means a chapter was missed or duplicated in the list.

When a chapter is damaged

Chaptering interacts badly with battery failure. If the camera dies while writing, the final chapter loses its moov index, because that index is written last. The chapter is large and unplayable, and the join fails on it while the earlier chapters are fine.

Test each chapter individually before joining:

for f in GX0*0042.MP4; do
  printf '%s: ' "$f"
  ffprobe -v error -show_entries format=duration -of csv=p=0 "$f" || echo "NO DURATION"
done

Any chapter reporting no duration needs repair before it can be joined. Manatee rebuilds the missing index from the surviving frame data and writes a clean copy, working from a duplicate so the card original stays as it is, after which the repaired chapter joins normally with the others. Repairing a corrupted GoPro or drone video goes through that in more detail, and salvaging a half-copied video covers the related case where the copy off the card was interrupted rather than the recording.

Avoiding chapters in the first place

You mostly cannot, and you would not want to. The 4 GB limit is a property of the card’s file system, and formatting a card exFAT rather than FAT32 raises the ceiling considerably, but cameras often still chapter at a set size for safety: if one file is damaged you lose one chapter rather than an entire hour.

Format cards in the camera rather than on the Mac. The camera chooses a layout it can write reliably at high bitrate, and a card formatted elsewhere occasionally produces dropped frames that are hard to diagnose later.

Questions

Does joining lose quality? Not with -c copy. Nothing is decoded or re-encoded, so the picture in the joined file is identical to the picture in the chapters.

Can I join chapters from two different recordings? Technically yes, if the settings match, and the result is one file containing two takes. If the settings differ, -c copy fails and you would need a re-encode.

The join worked but audio drifts after the first chapter. That points at a chapter boundary where the audio and video lengths differ slightly. Re-encoding the audio while copying the video usually resolves it: add -c:v copy -c:a aac instead of -c copy.

Is there a frame missing at each boundary? Usually at most one, and in practice it is not visible. The camera closes one file and opens the next as quickly as it can.