EU AI Act Article 50(4): building deepfake and AI-text labels your customers can actually ship
If your product lets business users generate or edit images, audio or video of real-looking people, places or events, Article 50(4) of the EU AI Act is the duty your customers will ask you about. It's a deployer duty: th
If your product lets business users generate or edit images, audio or video of real-looking people, places or events, Article 50(4) of the EU AI Act is the duty your customers will ask you about. It's a deployer duty: the company publishing the content has to tell people it's AI-generated. But the deployer can only do that easily if your product gives them the tools.
This post covers what 50(4) actually requires, why the C2PA mark you embed under Article 50(2) doesn't satisfy it, and a small, practical labeling layer: a data model, a visible label component, an audio disclosure, and an audit log. It's readiness support for developers, not legal advice, and it was AI-assisted and then edited.
What Article 50(4) says
From Regulation (EU) 2024/1689, Article 50, closely paraphrased:
- Deepfakes: deployers of an AI system that generates or manipulates image, audio or video content constituting a deep fake "shall disclose that the content has been artificially generated or manipulated."
- Creative carve-down (not carve-out): where the content is part of an "evidently artistic, creative, satirical, fictional or analogous work or programme", the duty is limited to disclosing that such content exists "in an appropriate manner that does not hamper the display or enjoyment of the work."
- Public-interest text: deployers of a system that generates or manipulates text "published with the purpose of informing the public on matters of public interest" must disclose that too, unless the text has gone through human review or editorial control and a person holds editorial responsibility for it.
- Law enforcement exception applies to both.
Article 50(5) then says how: the information goes to people "in a clear and distinguishable manner at the latest at the time of the first interaction or exposure" and must meet applicable accessibility requirements.
And Article 3(60) defines a deep fake as "AI-generated or manipulated image, audio or video content that resembles existing persons, objects, places, entities or events and would falsely appear to a person to be authentic or truthful."
Three things the Commission's FAQ clarifies
The Commission's Article 50 FAQ (dated 24 July 2026) adds useful detail:
- Deepfake is a three-part test: resemblance, to something that exists or plausibly could, and a false appearance of being authentic. Context and audience expectations matter, so routine background effects in film production are given as an example that's unlikely to qualify.
- The machine-readable mark is not the label. Disclosure must be perceivable "without need for any specific technical tools", for example a visible or audible label, so deployers "cannot simply rely on the machine-readable marking" from the provider.
- Human review means substance. For the text exemption, spell-checking or grammar fixes don't count; it has to be real review or editorial control by someone with the relevant knowledge.
The FAQ also says Article 50 applies from 2 August 2026, and the only grace period (to 2 December 2026) covers the provider-side 50(2) marking duty for systems already on the market. There's no grace period for 50(4). Fines for Article 50 breaches can reach β¬15 million or 3% of worldwide annual turnover, per the same FAQ.
The engineering problem
Your 50(2) work puts a signed manifest inside the file. Your 50(4) work has to make sure a human sees or hears a disclosure every time the content is shown, in every surface: your app, embeds, exports, and social crops. That's a product feature, not a metadata field.
A workable design has four parts.
1. Store the disclosure decision with the asset
Don't make the label a CSS afterthought. Store it next to the asset so every renderer and exporter reads the same answer:
// asset-disclosure.ts
export type DisclosureMode =
| "full" // standard deepfake label, always visible
| "creative" // evidently artistic/satirical/fictional work: lighter-touch notice
| "text-public" // AI text on matters of public interest, no editorial review
| "none"; // not a deepfake / reviewed text, with a recorded reason
export interface AssetDisclosure {
assetId: string;
mediaType: "image" | "video" | "audio" | "text";
aiGenerated: boolean;
mode: DisclosureMode;
reason: string; // why this mode was chosen, in plain words
decidedBy: string; // user id of the person who chose it
editorialReviewer?: string; // required when text skips labeling
labelText: string; // what people will actually see/hear
decidedAt: string; // ISO timestamp
}
export function validate(d: AssetDisclosure): string[] {
const errors: string[] = [];
if (d.aiGenerated && d.mode === "none" && !d.reason.trim()) {
errors.push("AI-generated asset marked 'none' needs a recorded reason.");
}
if (d.mediaType === "text" && d.mode === "none" && d.aiGenerated && !d.editorialReviewer) {
errors.push("Unlabeled AI text needs a named editorial reviewer.");
}
if (d.mode !== "none" && !d.labelText.trim()) {
errors.push("A label mode needs label text.");
}
return errors;
}
Default mode to "full" for any AI-generated image, video or audio of a realistic subject, and let the deployer downgrade it with a reason. Deciding whether something is a deepfake is a judgment call for the deployer, so your job is to make the safe choice the default and record who changed it.
2. A visible label that survives layout
The label should be on or directly next to the media, present at first exposure, and readable by assistive tech:
// AiMedia.tsx
import type { AssetDisclosure } from "./asset-disclosure";
export function AiMedia({ src, alt, disclosure }:
{ src: string; alt: string; disclosure: AssetDisclosure }) {
const showLabel = disclosure.aiGenerated && disclosure.mode !== "none";
const labelId = `ai-label-${disclosure.assetId}`;
return (
<figure className="ai-media" aria-describedby={showLabel ? labelId : undefined}>
<img src={src} alt={alt} />
{showLabel && (
<figcaption
id={labelId}
className={disclosure.mode === "creative" ? "ai-label ai-label--subtle" : "ai-label"}
>
{disclosure.labelText}
</figcaption>
)}
</figure>
);
}
.ai-media { position: relative; display: inline-block; }
.ai-label {
position: absolute; left: 8px; bottom: 8px;
padding: 2px 8px; border-radius: 4px;
background: rgba(0,0,0,.75); color: #fff;
font: 600 13px/1.4 system-ui, sans-serif;
}
.ai-label--subtle { background: rgba(0,0,0,.6); font-size: 12px; font-weight: 500; }
Notes from building these:
- Put the label in the DOM, not baked only into a hover tooltip. "Hover to see" is a dedicated action, and the FAQ says disclosure shouldn't require one.
- Keep a contrast ratio of at least 4.5:1 for the label text (WCAG 2.2 contrast minimum) since 50(5) calls for accessibility.
- For the
creativemode, a subtle corner tag or an opening/closing credit is the kind of thing that "does not hamper the display or enjoyment of the work".
3. Burn it in on export
Social platforms strip metadata and crop captions. If users can download or share, offer a burned-in label on export. With ffmpeg, a video label is one filter:
ffmpeg -i in.mp4 -vf "drawtext=text='AI-generated video':x=16:y=h-th-16:fontsize=28:fontcolor=white:box=1:[email protected]:boxborderw=8" -c:a copy out.labeled.mp4
For images, ImageMagick does the same:
magick in.jpg -gravity SouthWest -fill white -undercolor '#000000A0' -pointsize 28 -annotate +16+16 'AI-generated image' out.labeled.jpg
Keep the C2PA manifest too. Re-sign after burning in the label so the provenance chain records the edit.
4. Audio needs an audible disclosure
A synthetic voice clip has no corner to put a badge on. Prepend a short spoken notice, and also show text wherever there's a player:
# notice.wav: a short recorded "This audio was generated with AI."
ffmpeg -i notice.wav -i clip.wav -filter_complex "[0:a][1:a]concat=n=2:v=0:a=1[out]" -map "[out]" clip.disclosed.wav
Both inputs need matching sample rate and channel layout for concat; resample with -ar and -ac first if they differ.
Log it so you can prove it later
If a regulator, platform, or customer asks, you want to show what label was shown and who decided. Append one line per decision and per render surface:
{"ts":"2026-11-03T15:02:11Z","assetId":"a_81f2","event":"disclosure_set","mode":"full","labelText":"AI-generated image","decidedBy":"u_204"}
{"ts":"2026-11-03T15:04:40Z","assetId":"a_81f2","event":"exported","surface":"download","burnedIn":true,"c2paResigned":true}
Keep this append-only, and include the label text verbatim so wording changes are traceable.
A short checklist
- [ ] AI image/video/audio of realistic subjects defaults to a visible or audible label.
- [ ] Downgrading to
creativeornonerequires a reason and a named person. - [ ] Unlabeled AI text on public-interest topics requires a named editorial reviewer.
- [ ] Labels appear at first exposure, need no hover or click, and meet contrast and screen-reader basics.
- [ ] Exports can burn in the label; C2PA is re-signed after.
- [ ] Every disclosure decision and export is logged.
If you'd like a quick read on where your own product lands across Article 50 (chatbot disclosure, 50(2) marking, and 50(4) labeling), RuleReddy has a free Article 50 check at rulereddy.com.
Not legal advice. This is general technical guidance; check the official text and the Commission's guidance, and talk to counsel for decisions about your specific product.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.