DEV Community

Best Sites
Best Sites

Posted on Fully Autonomous

Why a 15-second MP4 can exceed an AI video reference limit

A player showing “0:15” does not prove that an MP4 fits a 15-second reference limit. The video stream, audio stream, and container can report different durations. An output duration: 15 setting also does not necessarily trim an uploaded reference.

AI disclosure: This article was drafted with AI assistance. The commands and synthetic example were checked locally with FFmpeg 7.1.1; no paid model calls were used.

Reproduce the mismatch

Run this in an empty directory with FFmpeg installed. It deliberately creates 15 seconds of video and slightly longer audio. -n prevents overwriting existing files.

ffmpeg -hide_banner -loglevel error -n \
  -f lavfi -i 'testsrc2=size=320x180:rate=24:duration=15' \
  -f lavfi -i 'sine=frequency=440:sample_rate=44100:duration=15.07' \
  -map 0:v:0 -map 1:a:0 \
  -c:v libx264 -preset ultrafast -pix_fmt yuv420p \
  -c:a aac demo.mp4
Enter fullscreen mode Exit fullscreen mode

There is no -shortest: the mismatch is intentional. Inspect the actual file rather than the rounded player display:

ffprobe -v error \
  -show_entries 'format=duration,start_time:stream=index,codec_type,codec_name,duration,start_time,nb_frames' \
  -of json demo.mp4
Enter fullscreen mode Exit fullscreen mode

In the local test, the video stream was 15.000000 seconds / 360 frames, while the audio stream and container were 15.070000 seconds. Exact values can vary with the encoder and version. A validator checking the longer timeline sees a reference longer than 15 seconds. This synthetic test does not establish how any particular AI service validates files.

Inspect presentation endpoints when metadata is unclear

For a deeper diagnostic, inspect packet presentation timestamps and durations. This script reports the largest PTS + duration for each stream:

import json
import subprocess
from decimal import Decimal

data = json.loads(subprocess.check_output([
    "ffprobe", "-v", "error", "-show_packets",
    "-show_entries", "packet=stream_index,pts_time,duration_time",
    "-of", "json", "demo.mp4"
], text=True))

ends = {}
missing = 0
for packet in data["packets"]:
    if "pts_time" not in packet or "duration_time" not in packet:
        missing += 1
        continue
    stream = packet["stream_index"]
    end = Decimal(packet["pts_time"]) + Decimal(packet["duration_time"])
    ends[stream] = max(ends.get(stream, end), end)

print({stream: str(end) for stream, end in ends.items()})
print("Packets needing further inspection:", missing)
Enter fullscreen mode Exit fullscreen mode

The test produced endpoints of 15.000000 for video and 15.070000 for audio. Use the maximum presentation endpoint, rather than assuming the final packet in file order has the latest presentation time.

This is a diagnostic, not a universal duration validator. Nonzero start times, edit lists, codec delay, variable frame rate, and missing packet timestamps need further inspection. An absolute endpoint is not automatically a duration; account for the relevant timeline start and the service’s validation rules.

Remove the extra audio only when the API permits it

For this particular file, the video already fits. If a silent reference is accepted, removing audio avoids re-encoding the video:

ffmpeg -hide_banner -loglevel error -n -i demo.mp4 \
  -map 0:v:0 -an -c:v copy -movflags +faststart video-only.mp4
Enter fullscreen mode Exit fullscreen mode

Re-run the probes on video-only.mp4. In the local test, its container duration, video duration, and maximum video packet endpoint were all 15.000000 seconds.

This command removes audio; it does not generally trim an overlong video. If audio is required, trim and re-encode the necessary tracks, then inspect the output again. Stream-copy cuts can be constrained by keyframes, and a separate soundtrack is useful only if the API explicitly supports one.

Before uploading a reference

  • Check the container duration and each stream’s duration and start time.
  • Investigate packet timing when metadata is ambiguous.
  • Verify the exported file after every trim or audio change.
  • Check the endpoint’s input limits independently of its output settings.
  • Treat API acceptance and visual quality as separate checks.

Validate the media you actually upload, as well as the JSON request.

References: FFprobe documentation and FFmpeg documentation.

Top comments (0)