Skip to content

Join clips

A terminal: pconv join intro.mp4 scene.mp4 outro.mp4 film.mp4 prints film.mp4 and says it joined 3 clips by stream copy, no re-encode, since every clip is h264 1280x720 at 30 fps with aac stereo at 48000 Hz; then pconv join film.mp4 phone.mp4 cut.mp4 says it joined 2 clips by re-encoding to 1280x720 at 30 fps, because phone.mp4 is 720x1280.

pconv join stitches two or more clips, in the order given, into one mp4, mov, mkv or webm. The last name is the output.

$ pconv join intro.mp4 scene.mp4 outro.mp4 film.mp4
film.mp4
joined 3 clips by stream copy, no re-encode: every clip is h264 1280x720 at 30 fps with aac stereo at 48000 Hz

When every clip matches the first (codec, profile, size, pixel aspect, rotation, rate, pixel format, colour tags, codec headers and audio), pconv copies every packet through ffmpeg’s concat demuxer. Three 30 s 1080p clips join in 0.42 s this way, against 21.6 s re-encoded.

$ pconv join film.mp4 phone.mp4 cut.mp4
cut.mp4
joined 2 clips by re-encoding to 1280x720 at 30 fps (balanced): phone.mp4 is 720x1280, not 1280x720 like film.mp4

Otherwise pconv re-encodes every clip to the first one’s size and rate with the profile (balanced by default), letterboxing a clip of another shape and giving a clip without audio silence of its own length. It says which clip didn’t match and why.

Any of --profile, --size, --fps, --crf, --qp or --tune asks for a re-encode, even of matching clips:

pconv join a.mp4 b.mp4 c.mp4 whole.mp4 --size 720p --profile best

--loudness and --audio-bitrate apply to the joined audio; see loudness.

With --json, the manifest has sources (each clip’s path and sha256) and join with its method (copy or encode), reason and clips; see the formats reference.