Upscale a Video
Use video upscaling when a finished MP4 needs a larger resolution for delivery on high-resolution screens or platforms. Choose a 1080p, 2k, or 4k target, and Mirako enlarges the video without cropping or stretching it.
Video upscaling is asynchronous. You receive a task ID first, then wait for the MP4 result or return later to retrieve it.
Before You Start
Prepare a video that meets these requirements:
| Requirement | Supported value |
|---|---|
| Container | MP4 |
| Video | H.264, 8-bit SDR, progressive, constant frame rate, square pixels |
| Audio | AAC or no audio |
| Maximum file size | 1 GiB |
| Maximum duration | 10 minutes |
| Frame limits | Up to 60 fps and 18,000 total frames |
| Source dimensions | Each side up to 4096 pixels and up to 2,100,000 pixels in total |
Note: Every video upscale task has a minimum billable duration of 5 seconds. For example, a 2-second video is billed as 5 seconds. This minimum affects billing only; the output video keeps its original duration.
Choose a target larger than the source. Mirako preserves the source aspect ratio, fits it inside the selected target box, and limits enlargement to 4×.
| Target | Landscape box | Portrait box |
|---|---|---|
1080p |
1920×1080 | 1080×1920 |
2k |
2560×1440 | 1440×2560 |
4k |
3840×2160 | 2160×3840 |
Note: The target is a bounding box, not a request to crop the video to an exact aspect ratio. For example, a 4:3 source remains 4:3.
If this is your first Mirako request, complete Authentication before continuing.
Quick Start with the CLI
Upscale a video to the 1080p target, wait for completion, and save the MP4:
mirako video upscale \
--video launch-clip.mp4 \
--resolution 1080p \
--output launch-clip-1080p.mp4
The CLI submits the task and polls until it can download the result. For a background workflow, submit without waiting and keep the printed task ID:
mirako video upscale \
--video launch-clip.mp4 \
--resolution 2k \
--no-wait
mirako video upscale status <task-id> --output launch-clip-2k.mp4
If the status command reports that work is still in progress, run it again later.
| Option | Required | Description |
|---|---|---|
--video |
Yes | Path to the MP4 file. |
--resolution, -r |
Yes | Target: 1080p, 2k, or 4k. |
--output, -o |
No | Where to save the completed MP4. |
--poll-interval, -p |
No | Status interval in seconds. Defaults to 2. |
--no-wait |
No | Return after submission. Cannot be combined with --output. |
--no-save, -n |
No | Wait for completion and print the temporary result URL instead of downloading it. |
Integrate with the REST API
Set your API key as the MIRAKO_API_KEY environment variable. The following example submits an MP4, polls every 10 seconds, and downloads the completed result. Store the task ID in a durable place if your process may restart.
import os
import shutil
import time
from pathlib import Path
import requests
API_KEY = os.environ["MIRAKO_API_KEY"]
BASE_URL = "https://mirako.co"
INPUT_PATH = Path("launch-clip.mp4")
OUTPUT_PATH = Path("launch-clip-1080p.mp4")
POLL_INTERVAL = 10
MAX_WAIT_SECONDS = 30 * 60
headers = {"Authorization": f"Bearer {API_KEY}"}
try:
with INPUT_PATH.open("rb") as video_file:
response = requests.post(
f"{BASE_URL}/v1/video/upscale",
headers=headers,
params={"resolution": "1080p"},
files={"file": (INPUT_PATH.name, video_file)},
timeout=900,
)
response.raise_for_status()
task = response.json()["data"]
task_id = task["task_id"]
print(f"Submitted task {task_id}")
deadline = time.monotonic() + MAX_WAIT_SECONDS
while task["status"] in {"IN_QUEUE", "IN_PROGRESS"}:
if time.monotonic() >= deadline:
raise TimeoutError(f"Task {task_id} did not finish in time")
time.sleep(POLL_INTERVAL)
status_response = requests.get(
f"{BASE_URL}/v1/video/upscale/{task_id}",
headers=headers,
timeout=60,
)
status_response.raise_for_status()
task = status_response.json()["data"]
print(f"Status: {task['status']} ({task['stage']})")
if task["status"] != "COMPLETED":
error = task.get("error", {})
raise RuntimeError(error.get("message", f"Task ended as {task['status']}"))
output = task["result"]["output"]
with requests.get(output["file_url"], stream=True, timeout=300) as download:
download.raise_for_status()
with OUTPUT_PATH.open("wb") as output_file:
shutil.copyfileobj(download.raw, output_file)
print(f"Saved {output['width']}×{output['height']} MP4 to {OUTPUT_PATH}")
print(f"Result remains available until {output['readable_until']}")
except (requests.RequestException, RuntimeError, TimeoutError) as error:
response = getattr(error, "response", None)
detail = response.text if response is not None else str(error)
raise SystemExit(f"Video upscale failed: {detail}") from error
| Parameter | Location | Required | Description |
|---|---|---|---|
file |
Multipart form | Yes | MP4 video, up to 1 GiB. |
resolution |
Query | Yes | 1080p, 2k, or 4k. |
webhook_url |
Multipart form | No | Public HTTPS URL that receives the terminal task payload, up to 1000 bytes. |
webhook_token |
Multipart form | No | Token sent as Authorization: Bearer <token>, up to 512 bytes. Requires webhook_url. |
task_id |
Path | For status checks | ID returned by the submit request. |
See the Upscale Video API reference for the complete request and response schema.
Use a Webhook Instead of Polling
For a serverless or event-driven application, include webhook_url in the multipart form. Mirako sends the terminal task payload once when processing completes. The URL must use public HTTPS, and redirects are not followed.
Use webhook_token to authenticate the callback, and still store the task ID so you can recover with GET /v1/video/upscale/{task_id} if delivery fails. See Handle Async Tasks for general polling and webhook guidance.
Download the Result Promptly
A completed task provides the temporary MP4 URL at data.result.output.file_url, plus dimensions, duration, frame rate, and readable_until.
The result remains available for 24 hours after it is created. A signed URL can expire sooner; poll the task endpoint again before readable_until to obtain a fresh URL. After that time, the API returns 410 RESULT_EXPIRED.
Going Next
Use Talking Avatar Videos or Avatar Motion Videos when you need to create a new avatar video before upscaling it.