feat: keep MOV in video allow-list, drop only WebM

Previous attempt dropped both video/quicktime and video/webm citing
narrow platform support. Re-investigated:

- Modern .mov files (iPhone recordings, screen captures) are ISO BMFF
  containers — the same format MP4 uses. Social platforms decode them
  like MP4 even when PHP's mime_content_type() reports
  'video/quicktime'. Postiz quietly accepts MOV via this same trick:
  their file-type lib detects the magic bytes as 'video/mp4' and
  renames the upload before storage.

- WebM is genuinely incompatible (Matroska + VP8/VP9 stack) — X / IG /
  TikTok / FB / Pinterest / Bluesky / Threads all reject it.

So allow MOV, keep WebM out. Rejecting MOV would force every iPhone
user to transcode before uploading — real UX cost for no gain since
the publishers handle it.
This commit is contained in:
Paulo Castellano 2026-05-04 15:12:32 -03:00
parent 332513e360
commit ffdedfe29d

View file

@ -18,20 +18,32 @@ public function label(): string
}
/**
* Allow-list of MIME types we accept on upload / URL fetch.
*
* Video accepts MP4 plus QuickTime/MOV. Modern .mov files (iPhone
* recordings, screen captures) are ISO BMFF containers the same
* format MP4 uses so social platforms decode them like MP4 even
* if PHP reports `video/quicktime`. Accepting MOV avoids forcing
* iPhone users to transcode before uploading.
*
* WebM is rejected: X / IG / TikTok / FB / Pinterest / Bluesky /
* Threads all reject the Matroska + VP8/VP9 stack. Without
* server-side transcoding, accepting WebM would just produce
* platform-specific publish failures down the line.
*
* @return array<int, string>
*/
public function allowedMimeTypes(): array
{
return match ($this) {
self::Image => ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
self::Video => ['video/mp4', 'video/quicktime', 'video/webm'],
self::Video => ['video/mp4', 'video/quicktime'],
};
}
/**
* Filename extensions that match this type. Used by callers that
* validate by name (chunked upload, URL fetch fallback) instead of
* by MIME.
* Filename extensions that match this type. Mirrors allowedMimeTypes
* for callers that validate by name instead of MIME.
*
* @return array<int, string>
*/
@ -39,7 +51,7 @@ public function extensions(): array
{
return match ($this) {
self::Image => ['jpg', 'jpeg', 'png', 'gif', 'webp'],
self::Video => ['mp4', 'mov', 'webm'],
self::Video => ['mp4', 'mov'],
};
}