User guide
For journalists, producers and editors using Newsroom in WordPress, and for the developers who connect it.
What it does
Newsroom turns a video from your Media Library into versions ready for publishing:
| Option | You get | Use it for |
|---|---|---|
| Web video (MP4) | A copy that plays everywhere, at the original size | Raw camera or phone files (.MOV, .MTS, .MXF) that won't play on your site |
| Web video, 720p | A smaller copy, 720 lines high | Article embeds, readers on mobile data |
| Vertical (9:16) | A 1080×1920 portrait video | Reels, Shorts, TikTok, Stories |
| Square (1:1) | A 1080×1080 video | Social feeds |
| Thumbnail | A still image from the video | Poster images and article thumbnails |
The new file is added to your Media Library next to the original. The original is never changed.
It can also make vertical news reels from your articles, with a voiceover, captions, your branding and your sponsor. See Making news reels.
How to use it
- Open the video in the Media Library, or in the post you're editing.
- Choose the version you want, for example Make vertical version.
- Carry on working. The status shows Queued, then Processing, then Ready.
- When it says Ready, the new file is in the Media Library.
Short clips are usually ready quickly; long or 4K videos take longer. If other videos from your newsroom are already processing, yours waits its turn and starts automatically. Processing stops after 30 minutes.
Making news reels
With the Newsroom Video plugin, Newsroom also makes vertical news videos from your published articles. Each one has an AI-written script read by an AI voice, the article's featured image as the background, captions, your logo and colours, and, if you have one, the current sponsor. Reels are made on our servers, so nobody has to keep a browser tab open, and they always come out as MP4: 1080×1920, ready for Reels, Shorts and TikTok.
Example 1: a video for one story
- In WordPress, open Newsroom Video → Generate Video.
- Leave the date filter on Today and tick one article, e.g. Council approves new library for Romford. The length box changes to your single-story default, such as 22 seconds.
- Click Generate Script. Read the script and caption and correct anything, especially names, places and anything legal. Then click Next: Render Video.
- On the render page, change the per-video controls if you want to, e.g. a bigger caption size, or the image panning right to left. Then click Render Vertical Video.
- The status box shows the reel's progress. You can leave the page at any point. When it's done, the preview, a download button and the OnlySocial box appear.
What the status box shows on a quiet day:
Sending the video to the Newsroom Video service… Queued on the Newsroom Video service: 1st in line, starting now. You can leave this page. Rendering on the server: 35%. You can leave this page. Rendering on the server: 80%. You can leave this page. Finished. Saving the video to WordPress… Video saved as MP4.
A reel takes roughly twice its own length to make. A 22-second story is usually ready in under a minute, and a 45-second bulletin in about a minute and a half. If other videos are waiting, yours queues first and the status box shows its place in line.
Example 2: a bulletin of three stories
Tick three articles instead of one (up to five are allowed). The length suggestion rises to 45 seconds, and the script covers each story in turn. In the video, each article gets its own scene with its own image and headline, and each scene lasts about as long as that story's part of the script. Everything else works as in Example 1.
Example 3: a video made automatically when an article is published
- Write the article as usual. In the AI News Video box on the edit screen, leave Generate an AI video when this article is first published ticked. Untick it for articles that shouldn't get a video.
- Publish. WordPress writes the script and voiceover, then sends the reel to our servers.
- Follow it in Newsroom Video → Rendering Queue. The article shows Server Rendering, with notes like Queued on the Newsroom Video service (2 in line) or Rendering on the Newsroom Video service (45%), and then Completed.
- If automatic OnlySocial posting is set up, the finished video goes out to your chosen accounts as well.
Automatic videos skip the script review. That's fine for routine stories, but for court cases, police appeals and allegations, untick the box and make the video yourself (Example 1), so that someone reads the script first.
Example 4: a video for every story today
On Generate Video, tick Create and publish a separate video for every article shown by this filter. The button becomes Create & Publish 6 Videos, or however many articles the filter shows. Each article gets its own reel, queued together. The service takes the videos one after another, so a batch of six takes several minutes. Other newsrooms' videos aren't held up meanwhile, because newsrooms take turns.
Example 5: landscape and square versions, a thumbnail and captions
For YouTube, Facebook or your own website you may want a landscape copy of each reel too. In Settings → Rendering → Also make, tick what you want with every vertical video:
- Landscape 16:9 video (1920×1080), for YouTube, Facebook and websites;
- Square video (1080×1080), for feeds;
- Thumbnail image, a JPEG of the first story;
- Caption files (.srt and .vtt), for platforms that show their own subtitles, such as YouTube.
Render as usual. When the reel is saved, buttons under the preview download each extra file, and the extra videos appear in the OnlySocial Video file list. They're all made from the same script, voiceover and settings, and the layout fits each shape. Automatic videos (Example 3) get the extras too.
Two more settings in the same place:
- Voiceover loudness evens out volume between videos. The default, −14 LUFS, is what Instagram, TikTok, YouTube and Facebook aim for, so your reels aren't turned down or left quiet.
- Maximum video length stops a video that's too long for where you post it. For example, set 90 if you post Facebook Reels. It's checked before the video is made, so a refused video costs nothing. Platforms change their limits, so check theirs.
Image motion also has Zoom in, Zoom out and Alternate (in on one story, out on the next), in Settings and on the render page.
How much allowance a reel uses
A reel counts the whole finished video, start and end screens included. For example:
| Start screen | 2.5 s |
| Voiceover | 40 s |
| Hold after the voiceover (End audio delay) | 3.5 s |
| End screen | 2.5 s |
| Counted against your allowance | 49 s |
|---|
At that length, the Starter plan's 10 hours is about 730 reels a month, and Pro's 50 hours over 3,600. Reels that fail don't count.
Each extra video format counts the same again: a 49-second reel in vertical and landscape uses 98 seconds. Thumbnails and caption files are free.
Setting it up (site administrators)
- Install version 3.0 or later of the Newsroom Video plugin (2.10 for vertical videos only).
- Go to Newsroom Video → Settings → Rendering. Set Render videos to On the Newsroom Video service, enter the service address (it starts
https://) and paste your API key. Then save. - Open System Status. Video renderer should say something like Newsroom Video service, connected (pro plan, 2,950 of 3,000 minutes left this month).
The service downloads each reel's voiceover and images from your website, so:
- your site needs
https://; - it must be reachable from the internet. A staging site behind a password won't work;
- if you use a firewall or bot protection such as Cloudflare or Wordfence, it must let requests with the user agent
NewsroomVideoRenderer/1.0through.
Rendering in the browser instead. Set Render videos to In this browser and videos are made in the editor's browser tab, as in earlier versions. That uses none of your allowance, but the tab must stay open until the video is saved, automatic videos wait for someone to open the browser worker (unless your web server has FFmpeg), and some browsers produce WebM rather than MP4. On the render page you can also use Render in this browser instead for a single video. If the service address or key is missing, the plugin uses the browser automatically.
If a reel goes wrong
| You see | What to do |
|---|---|
| "The service could not download the voiceover from this site…" | Check the site is live on https, and that your firewall or bot protection allows NewsroomVideoRenderer/1.0. Then render again |
| "Server rendering needs the voiceover on an https:// address…" | Your site's uploads use http://. Switch the site to https, or use Render in this browser instead |
| "Server rendering is selected, but the Newsroom Video API address or key is missing…" | Ask your site administrator to complete Settings → Rendering. Until then, videos render in the browser |
| "The voiceover file could not be read." | Go back to the script and click Next: Render Video again, which makes a fresh voiceover |
| "This video is longer than allowed…" | Shorten the script or use fewer stories, or raise Maximum video length in Settings → Rendering if it's set lower than you need |
| "This month's Newsroom Video allowance is used up." | Render in the browser until the 1st, or ask about upgrading |
| "The finished video expired before WordPress collected it." | Render it again. Finished reels are kept for 24 hours |
| A missing article image | The reel still renders, using the plain blue background for that story. Check the article's featured image is set and public |
| Server Rendering in the Rendering Queue for a long time | Open the Rendering Queue page: viewing it also checks on renders in progress. After 2 hours it's marked failed; use Retry |
Files you can use
| Works | Doesn't work |
|---|---|
| MP4, MOV, M4V, 3GP (phones, most cameras and editors) | AVI, WMV, FLV |
| MKV, WebM | Animated GIFs |
| MTS / M2TS (AVCHD camcorders) | Audio-only files (MP3, WAV, M4A) |
| MXF (broadcast cameras) | Files over 4096 pixels wide or high (8K) |
Plans and limits
| Trial | Starter | Pro | |
|---|---|---|---|
| Largest file | 500 MB | 2 GB | 2 GB |
| Longest video | 10 minutes | 30 minutes | 60 minutes |
| Videos processed at once | 1 | 2 | 4 |
| Video allowance per month | 30 minutes | 10 hours | 50 hours |
The monthly allowance is shared by everyone in your newsroom. It's the total length of the videos you've processed, and it resets on the 1st of each month (UTC). Thumbnails count as one second, and videos that fail to process don't count at all.
The queue and priority processing
Newsrooms take turns: when several are waiting, each gets one video started before anyone gets a second. A newsroom that sends a big batch therefore waits for its own videos, not everyone else's.
Newsrooms with priority processing, an annual add-on or part of some plans, go first, taking turns with each other. A standard video that has waited a while is moved up to go alongside them, so it is never held back for long. Your account page shows which you have, and how long your recent videos waited.
Tips for good results
- Vertical and square versions crop the picture. They keep the centre of the shot and cut off the sides of a landscape video. Keep your subject in the middle, or film in portrait if you know you need a vertical video.
- Trim before you process. It's quicker and uses less of your allowance.
- Thumbnails are picked automatically from the first few seconds. For a particular moment, trim the video to start there first.
- Subtitles and extra audio tracks are not carried over. Only the main picture and the first audio track are kept.
Privacy and source protection
- Hidden information is removed from every processed file, including GPS location, camera and phone model, serial numbers and editing history.
- Copies are deleted from the service. The upload is deleted as soon as it has been processed, and the result once Newsroom has saved it, always within 24 hours.
- Videos are processed on our own servers and are never passed to a third-party processing or AI service.
Only the new file is cleaned. The original you uploaded to WordPress still has its metadata, so publish the processed version.
If something goes wrong
| You see | What to do |
|---|---|
| "This file type can't be processed…" | Export or save the video as MP4 or MOV and try again |
| "This file doesn't contain any video." | You've chosen an audio file or an image |
| "This video appears to be damaged…" | Copy the file from the camera or phone again, or re-export it |
| "This video is longer than your plan allows…" | Trim it to the limit shown and try again |
| "This file is larger than your plan allows…" | Trim it, or export at a lower quality |
| "This video's resolution is too high…" | Export at 4K (3840×2160) or lower |
| "Your newsroom has used this month's video processing allowance." | Ask your editor or site administrator. It resets on the 1st, or your newsroom can upgrade |
| "Other videos are being processed…" | Nothing. Yours will start on its own |
| "Video processing isn't available…" | Contact your site administrator |
| "This video took too long to process." | Try a shorter clip |
| "The processed file is no longer available." | Process the video again |
| Stuck on Processing for more than 30 minutes | Try again. If it happens again, contact your site administrator with the video's name and the time |
Checking your usage
Site administrators can see this month's allowance, daily and monthly history, recent jobs and the account's API keys on the Account page. Sign in with the email address registered for your newsroom and one of its API keys.
Programs can read the same headline figures from GET /v1/usage (see below).
We also email that address when your newsroom has used 80% of the month's allowance, again at 100%, and a week before one of your API keys expires.
API reference
Every /v1 call needs the header Authorization: Bearer nr_live_…. Make calls from your server, never from browser JavaScript. Read-only keys can look at jobs, downloads, usage and the webhook, but can't create, delete or change anything. A key may have an end date: in its last two weeks, responses include an api_key_expiring warning, so put the replacement key in your settings before then. Errors look like {"detail": "<code>", "message": "…", "docs_url": "…", "request_id": "…"}: switch on detail, and show or log the rest.
| Method | Path | Notes |
|---|---|---|
POST | /v1/jobs?preset=mp4 | The raw file is the request body (not multipart); Content-Length is required. Returns 202 {id, status, preset, preset_version} |
GET | /v1/jobs/{id} | status is uploading, queued, processing, complete, failed or expired. Also error, billable_seconds, download_url, and while queued queue_position (1 = next) and estimated_start_seconds (rough) |
GET | /v1/jobs/{id}/download | The output file. 409 if not finished, 410 if expired |
DELETE | /v1/jobs/{id} | Deletes the files early. Call this once WordPress has stored the output |
POST | /v1/renders | Makes a news reel from a JSON manifest (see below): vertical by default, plus landscape, square, a thumbnail and caption files if asked. Returns a job like an upload does, with progress while it renders and its outputs when done |
GET | /v1/usage | This month's used and remaining seconds, plan limits, presets and preset_versions, and api_key (its prefix, scope and expires_at) |
PUT | /v1/webhook | Body {"url": "https://…"}. Finished jobs are then POSTed to that address (see Webhooks). Returns the signing secret the first time |
GET / DELETE | /v1/webhook | The URL and the last 20 deliveries / turn webhooks off |
POST | /v1/webhook/test | Sends a ping event to your webhook |
Headers worth sending
Idempotency-KeyonPOST /v1/jobs: a value unique to the video and preset, such asattachment-123-mp4. Reuse it when you retry a failed or timed-out upload, and you get the original job back (withIdempotent-Replayed: true) instead of a second, billed job. A key that was used for a different preset returns422 idempotency_key_reused.User-Agentnaming your plugin and version, such asNewsroomVideo-WP/2.9.0 WordPress/6.6, so we can tell you before a change affects the version you run.X-Request-Id(optional): your own id for the call, 8 to 128 letters, digits,.,_,:or-. Every response carries one either way. Quote it when you contact support.
Warnings and changes
Every /v1 JSON response has a warnings array, usually empty. Show any entries to the site admin. Today it reports quota_nearly_used once 80% of the allowance is used. If something you use is going to be retired, you get a deprecated warning plus Deprecation and Sunset headers months beforehand. We only ever add to /v1, so ignore fields you don't recognise. Changes are listed in the changelog.
News reels
POST /v1/renders with a JSON body makes a 1080×1920 MP4 news reel: a voiceover, one to five article headlines and images, captions from the script, your logo and colours, an optional sponsor and start and end screens. The Newsroom Video plugin sends this for you. Images and the voiceover are given as https:// addresses we can download (public sites only), or small images inline as data: URLs. The body is limited to 1 MB. Follow the job with GET /v1/jobs/{id} and download it as usual. A reel is billed by its finished length, start and end screens included.
A full manifest. Only audio_url, script and articles (each with a title) are required; the rest use the plugin's defaults:
{
"audio_url": "https://news.example/wp-content/uploads/newsroom-video/nrv_1730113200.mp3",
"script": "The Riverside Daily News Update. Councillors have approved a new library for Romford…",
"story_scripts": ["Councillors have approved a new library for Romford…", "Step-free access opens at Hornchurch…"],
"articles": [
{ "title": "Council approves new library for Romford", "category": "Council", "image_url": "https://news.example/wp-content/uploads/2026/10/library.jpg" },
{ "title": "Hornchurch station step-free access opens", "category": "Transport", "image_url": "https://news.example/wp-content/uploads/2026/10/station.jpg" }
],
"logo_url": "https://news.example/wp-content/uploads/logo.png", "logo_size_percent": 19, "logo_white_bg": true,
"brand_colour": "#0b4f9c", "banner_text_colour": "#ffffff", "title_banner_opacity": 100,
"caption_font_size": 86, "caption_bg_opacity": 74, "caption_advance": 0.35,
"image_motion": "pan_left_right",
"show_ai_label": true, "ai_label_text": "Generated by AI",
"start_screen_url": "https://news.example/wp-content/uploads/start.png", "start_screen_duration": 2.5,
"end_screen_url": "https://news.example/wp-content/uploads/end.png", "end_screen_duration": 2.5,
"audio_tail_padding": 3.5,
"sponsor": { "company_name": "Acme Bakery", "text": "Fresh bread daily", "logo_url": "https://news.example/wp-content/uploads/acme.png" },
"outputs": ["vertical", "landscape", "thumbnail", "captions_srt", "captions_vtt"],
"loudness_lufs": -14,
"max_duration_seconds": 90
}
outputs: what to make, at least one video.vertical(1080×1920, the default),landscape(1920×1080),square(1080×1080),thumbnail(JPEG),captions_srtandcaptions_vtt. The first video listed is the main one. Each video is billed for its length; thumbnails and captions are free.loudness_lufs: normalise the voiceover, e.g. −14 for social media. Leave it out to keep it as it is.max_duration_seconds: refuse a video longer than this before rendering, unbilled (job errorduration_too_long).image_motion:auto,static, the four pans,zoom_in,zoom_outoralternate.
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -H "Idempotency-Key: reel-nrv_1730113200" \
--data @reel.json "https://this-server/v1/renders"
# {"id":"5c1e…","status":"queued","preset":"news_reel","preset_version":1,"status_url":"/v1/jobs/5c1e…","warnings":[]}
curl -H "Authorization: Bearer $KEY" https://this-server/v1/jobs/5c1e…
# {"id":"5c1e…","status":"queued","queue_position":2,"estimated_start_seconds":40,"progress":null,…}
# {"id":"5c1e…","status":"processing","progress":45,…}
# {"id":"5c1e…","status":"complete","progress":100,"duration_seconds":48.5,"billable_seconds":98,"download_url":"/v1/jobs/5c1e…/download",
# "outputs":[{"name":"vertical","media_type":"video/mp4","bytes":9120345,"width":1080,"height":1920,"download_url":"/v1/jobs/5c1e…/download?output=vertical"},
# {"name":"landscape",…}, {"name":"thumbnail",…}, {"name":"captions_srt",…}, {"name":"captions_vtt",…}],…}
curl -H "Authorization: Bearer $KEY" -o reel.mp4 https://this-server/v1/jobs/5c1e…/download
curl -H "Authorization: Bearer $KEY" -o reel-landscape.mp4 "https://this-server/v1/jobs/5c1e…/download?output=landscape"
curl -H "Authorization: Bearer $KEY" -o reel.srt "https://this-server/v1/jobs/5c1e…/download?output=captions_srt"
A mistake in the manifest is reported straight away, naming the field:
# {"detail":"invalid_manifest","message":"brand_colour must be a colour like #0b4f9c","docs_url":"…/guide#errors","request_id":"…"}
The same from PHP, with the example client (NewsroomFfmpegClient.php):
$api = new NewsroomFfmpegClient('https://this-server', $key, userAgent: 'MyPlugin/1.0 WordPress/6.6');
$job = $api->createRender($manifest, 'reel-' . $postId); // same key + same content = same job
// …later, from WP-Cron:
$job = $api->getJob($job['id']);
if ($job['status'] === 'complete') { $api->download($job['id'], $uploadsDir . '/reel.mp4'); $api->deleteJob($job['id']); }
Presets
Presets are versioned. preset=mp4 uses the current default version, and preset=mp4@1 pins version 1. A preset's output only changes through a new version announced in the changelog, so pin a version if you need output that never changes.
| Preset | Output |
|---|---|
mp4 | MP4 (H.264 + AAC) at the original resolution |
mp4_720p | MP4, downscaled to 720p if larger (never upscaled) |
vertical_1080x1920 | MP4 1080×1920, centre crop |
square_1080 | MP4 1080×1080, centre crop |
thumbnail_jpg | JPEG, up to 1280 wide; billed as 1 second |
Example
curl -H "Authorization: Bearer $KEY" -H "Idempotency-Key: clip-1-mp4" --data-binary @clip.mov "https://this-server/v1/jobs?preset=mp4" # {"id":"8d89…","status":"queued","preset":"mp4","preset_version":1,"warnings":[]} curl -H "Authorization: Bearer $KEY" https://this-server/v1/jobs/8d89… # poll every 10–30 s from a background task until status is complete or failed curl -H "Authorization: Bearer $KEY" -o out.mp4 https://this-server/v1/jobs/8d89…/download curl -X DELETE -H "Authorization: Bearer $KEY" https://this-server/v1/jobs/8d89…
Webhooks
Instead of polling, you can be told when a job finishes. Set an address once with PUT /v1/webhook and store the secret it returns. When a job finishes, we POST this to the address:
{"id":"0aaa…","type":"job.completed","created_at":"2026-10-30T19:24:58.612Z",
"data":{"job":{"id":"9dc6…","status":"complete","billable_seconds":22,"download_url":"/v1/jobs/9dc6…/download", …}}}
typeisjob.completed,job.failed(data.job.errorsays why) orping.- Check it's really from us. The
Newsroom-Signatureheader ist=<unix time>,v1=<signature>, where the signature is the hex HMAC-SHA256 of<t>.<raw body>with your secret. Reject it if it doesn't match, or iftis more than 5 minutes old. The PHP client'sNewsroomFfmpegClient::verifyWebhook()does both. - Answer
200within 10 seconds and download the video afterwards, in the background. Any other answer is retried after 1, 5, 30, 120, 360, 720 and 1440 minutes. - The same event can arrive twice; ignore an
idyou've already handled. Polling still works, so keep a slow poll as a backstop.
Upload with cURL streaming from disk (CURLOPT_UPLOAD + CURLOPT_INFILE) rather than wp_remote_post(), which loads the whole file into memory. Poll from WP-Cron or Action Scheduler, never inside an editor request.
Error codes
| HTTP | detail | Retry? | Meaning |
|---|---|---|---|
| 400 | empty_body, incomplete_upload, upload_failed | Once | The upload was cut off |
| 400 | invalid_idempotency_key | No | The key must be 1 to 255 printable ASCII characters |
| 422 | invalid_manifest | No | A render manifest field is missing or wrong; message says which |
| 413 | body_too_large | No | The render manifest is over 1 MB: link to images instead of inlining them |
| 401 | invalid_api_key | No | Key missing, wrong or revoked |
| 401 | api_key_expired | No | The key's end date has passed; use its replacement |
| 403 | insufficient_scope | No | A read-only key can't create or delete; use a full key |
| 422 | invalid_webhook_url | No | The webhook must be an https address on port 443 that resolves to a public address |
| 404 | webhook_not_set | No | Set a webhook before testing it |
| 404 | output_not_found | No | ?output= names an output the job doesn't have |
| 402 | quota_exceeded | No | Monthly allowance used |
| 403 | account_suspended | No | Contact support |
| 404 | job_not_found | No | Wrong id, or another account's job |
| 409 | job_not_complete, job_in_progress | Later | Too early to download or delete |
| 409 | idempotency_key_in_use | After 30 s | The first upload with this key is still arriving |
| 410 | job_expired | No | Output already deleted; submit again |
| 411 | content_length_required | No | Send Content-Length |
| 413 | file_too_large | No | Over the plan's upload limit |
| 416 | range_not_satisfiable | No | The download range starts past the end of the file |
| 422 | invalid_source_url | No | source_url must be a public https address on port 443 |
| 422 | unknown_preset | No | Use a preset (and version) from /v1/usage |
| 422 | idempotency_key_reused | No | The key was already used for a different preset; use a new key |
| 429 | too_many_active_jobs | After 60 s | At the concurrency limit, or rate-limited |
| 50x | With backoff | A deploy or an outage |
Job error values
error | Meaning |
|---|---|
unsupported_format | Not a supported video container, or not a video |
no_video_stream | No video track (e.g. audio only) |
unknown_duration | The file is damaged or truncated |
duration_too_long | Longer than the plan allows |
resolution_too_large | Wider or taller than 4096 pixels |
quota_exceeded | Would exceed this month's allowance |
timeout, probe_timeout | Took more than 30 minutes |
processing_failed | FFmpeg couldn't convert it, usually a corrupt file |
source_fetch_failed | We couldn't download the video from source_url. Check the link works without signing in, hasn't expired, and isn't blocking the NewsroomVideoRenderer user agent |
file_too_large | The video at source_url is over the plan's upload limit |
media_fetch_failed | Render: we couldn't download the voiceover. Check it's on a public https address and not blocked by a firewall or bot protection |
media_invalid | Render: the voiceover isn't MP3, M4A, WAV or Ogg audio |
render_failed | Render: the video couldn't be made. Send it again; contact support if it keeps happening |