Skip to content

Harden media constraints: backend validation, reliable video meta, square YouTube Shorts #200

Description

@paulocastellano

Context

Follow-up from #199 (YouTube Shorts max duration raised to 3 minutes in the dashboard).

Today, duration / aspect ratio / file-size limits live only in the frontend (useMediaRules.tsuseMedia.ts). API and MCP share ContentTypeCompatibleWithMedia, which only checks media type (image/video/document, requires media, mixed media) — not duration, dimensions, or bytes.

Media is post-level and shared across platforms (one posts.media array). Validation must stay per content_type against that shared set, not a single global limit on the file.

Goals

1. Reliable video meta on upload

Chunked uploads often store videos with empty meta. Duration/width/height used by the editor are client-supplied (or missing). Without a server probe (e.g. ffprobe), backend duration/aspect checks are forgeable or skipped.

  • Extract duration, width, height (and maybe size) when media is finalized on the server
  • Persist on asset / post.media[].meta so web, API, and MCP see the same values

2. Backend validation (web + API + MCP)

Extend ContentTypeCompatibleWithMedia (or a sibling rule) to enforce the same constraints as CONTENT_TYPE_RULES in useMediaRules.ts:

  • max duration (maxVideoDurationSec)
  • aspect ratio range (aspectRatioMin / aspectRatioMax)
  • max file size (maxVideoBytes / maxImageBytes / …)
  • file count / requires-media (where not already covered)

Apply on schedule/publish paths for:

  • Web (UpdatePostRequest)
  • Public API
  • MCP (Create/Update/Publish post tools)

Shared-upload model: evaluate each enabled platform’s content_type independently against the shared media (same as usePostCompliance on the frontend). Reject the failing platform(s) / block schedule when any selected platform is incompatible — do not invent per-platform media attachments.

Prefer a single source of truth for the numeric rules (PHP mirror of useMediaRules, or a shared definition both sides read) so dashboard and API/MCP don’t drift again.

TikTok: max duration is account-dynamic via creator_info.max_video_post_duration_sec — needs a deliberate approach (fetch at validate time vs leave TikTok frontend-only for now).

Missing meta: decide fail-open vs fail-closed once probe exists; until then, don’t rely on client-only duration.

3. Square YouTube Shorts

YouTube accepts Shorts that are square or vertical up to 3 minutes. Our dashboard still only allows ~9:16 (aspectRatioMin/Max ≈ 0.5–0.6) for youtube_short.

  • Widen allowed aspect ratio for youtube_short to include 1:1 (and confirm against current YouTube Shorts rules)
  • Update content-type copy / docs if needed
  • Keep backend rules in sync once (2) exists

Out of scope for this issue

Acceptance ideas

  • Video assets get server-measured meta.duration / dimensions after upload
  • Scheduling/publishing a post via API or MCP with a video over a content type’s max duration returns a validation error
  • Same for aspect ratio / size where rules define them
  • Multi-platform post: shared media valid for YT Short but over FB Reel’s 90s → FB Reel fails, YT can still pass (or schedule blocked only for the failing platform — match product rules used by the editor)
  • youtube_short accepts square (1:1) videos within the 3-minute cap
  • Frontend and backend limits stay aligned (no second silent drift)

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions