P-Video-Upscale

P-Video-Upscale is Pruna AI's video upscaling model for raising an existing clip to 720p, 1080p, 2K, or 4K while keeping its aspect ratio and audio track. It sharpens what is already in the frame without a prompt, can raise the frame rate to as much as 60 FPS by interpolating new frames, and offers a turbo mode that trades a little quality for speed. It works on live action, anime, game footage, and archival film, for bringing low-resolution generations or older footage up to delivery resolution.

Complete technical specification for integration
Ready-to-use code snippets for common workflows
Step-by-step tutorials for advanced use cases
← All GuidesUpscaling generated video
How to finish P-Video-2-Pro clips at 1080p, 2K or 4K with Pruna P-Video-Upscale: chaining by UUID, fitting the 4K frame cap, and choosing the render tier.
Introduction
P-Video-2-Pro renders at 480p or 768p. That is enough to judge a take, and short of what a 1080p feed or a 4K edit expects. P-Video-Upscale is the finishing step: it takes the generated clip by its UUID and returns it at 1080p, 2K or 4K, with the soundtrack the generation produced still attached.
The serum shot above came out of P-Video-2-Pro at 768p and went through a second request at 4k. The page plays both halves at the same size, so the gain is clearest at 100%, on the same patch of the bottle from each clip:


The 768p render was already clean, so the gain is in the finest edges: the pipette tip and the small bubbles suspended in the serum come through crisp at 4K.
This guide covers chaining the two requests, the clip lengths that fit a 4K finish, and whether to render at 480p or 768p before the upscale. The upscale request on its own, with every preset size, is in upscaling video.
Chaining the two requests
Generate the clip as usual. The response carries a videoUUID, and that UUID goes straight into inputs.video of the upscale, so the clip never has to be downloaded and sent back between the two steps.
import { createClient } from '@runware/sdk'
const client = await createClient({ apiKey: process.env.RUNWARE_API_KEY })
await client.connect()
const [result] = await client.run({
model: 'prunaai:p-video@2-pro',
deliveryMethod: 'async',
positivePrompt: 'A glass dropper bottle of amber facial serum stands on a wet slab of dark slate while slow ripples spread across a shallow film of water around its base, and a single clear drop falls from a glass pipette above into the water. A slow push-in at bottle height. Soft backlight glowing through the amber glass, crisp highlights on the wet stone and the water droplets. Photoreal skincare product commercial, no text, no logos, no label on the bottle. Audio: soft water drips, a quiet airy ambience, no music.',
width: 1344,
height: 768,
duration: 8,
seed: 2614093,
settings: {
mode: 'quality',
promptUpsampling: 'off'
}
})import asyncio
import os
from runware import Runware
async def main():
async with Runware(api_key=os.environ["RUNWARE_API_KEY"]) as client:
results = await client.run({
"model": "prunaai:p-video@2-pro",
"deliveryMethod": "async",
"positivePrompt": "A glass dropper bottle of amber facial serum stands on a wet slab of dark slate while slow ripples spread across a shallow film of water around its base, and a single clear drop falls from a glass pipette above into the water. A slow push-in at bottle height. Soft backlight glowing through the amber glass, crisp highlights on the wet stone and the water droplets. Photoreal skincare product commercial, no text, no logos, no label on the bottle. Audio: soft water drips, a quiet airy ambience, no music.",
"width": 1344,
"height": 768,
"duration": 8,
"seed": 2614093,
"settings": {
"mode": "quality",
"promptUpsampling": "off"
}
})
asyncio.run(main())curl https://api.runware.ai/v1 \
-H "Authorization: Bearer $RUNWARE_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"taskType": "videoInference",
"taskUUID": "3a5c7e9b-2d4f-4a6c-8e0b-1c3d5e7f9a2b",
"model": "prunaai:p-video@2-pro",
"deliveryMethod": "async",
"positivePrompt": "A glass dropper bottle of amber facial serum stands on a wet slab of dark slate while slow ripples spread across a shallow film of water around its base, and a single clear drop falls from a glass pipette above into the water. A slow push-in at bottle height. Soft backlight glowing through the amber glass, crisp highlights on the wet stone and the water droplets. Photoreal skincare product commercial, no text, no logos, no label on the bottle. Audio: soft water drips, a quiet airy ambience, no music.",
"width": 1344,
"height": 768,
"duration": 8,
"seed": 2614093,
"settings": {
"mode": "quality",
"promptUpsampling": "off"
}
}
]'runware run prunaai:p-video@2-pro \
deliveryMethod=async \
positivePrompt="A glass dropper bottle of amber facial serum stands on a wet slab of dark slate while slow ripples spread across a shallow film of water around its base, and a single clear drop falls from a glass pipette above into the water. A slow push-in at bottle height. Soft backlight glowing through the amber glass, crisp highlights on the wet stone and the water droplets. Photoreal skincare product commercial, no text, no logos, no label on the bottle. Audio: soft water drips, a quiet airy ambience, no music." \
width=1344 \
height=768 \
duration=8 \
seed=2614093 \
settings.mode=quality \
settings.promptUpsampling=off{
"taskType": "videoInference",
"taskUUID": "3a5c7e9b-2d4f-4a6c-8e0b-1c3d5e7f9a2b",
"model": "prunaai:p-video@2-pro",
"deliveryMethod": "async",
"positivePrompt": "A glass dropper bottle of amber facial serum stands on a wet slab of dark slate while slow ripples spread across a shallow film of water around its base, and a single clear drop falls from a glass pipette above into the water. A slow push-in at bottle height. Soft backlight glowing through the amber glass, crisp highlights on the wet stone and the water droplets. Photoreal skincare product commercial, no text, no logos, no label on the bottle. Audio: soft water drips, a quiet airy ambience, no music.",
"width": 1344,
"height": 768,
"duration": 8,
"seed": 2614093,
"settings": {
"mode": "quality",
"promptUpsampling": "off"
}
}Response
[
{
"taskType": "videoInference",
"taskUUID": "3a5c7e9b-2d4f-4a6c-8e0b-1c3d5e7f9a2b",
"videoUUID": "8b9c0d1e-2f3a-4b5c-9d6e-7f8a9b0c1d2e",
"videoURL": "https://vm.runware.ai/video/os/a14d18/ws/2/vi/8b9c0d1e-2f3a-4b5c-9d6e-7f8a9b0c1d2e.mp4"
}
]import { createClient } from '@runware/sdk'
const client = await createClient({ apiKey: process.env.RUNWARE_API_KEY })
await client.connect()
const [result] = await client.run({
model: 'prunaai:p-video@upscale',
deliveryMethod: 'async',
resolution: '4k',
inputs: {
video: '8b9c0d1e-2f3a-4b5c-9d6e-7f8a9b0c1d2e'
}
})import asyncio
import os
from runware import Runware
async def main():
async with Runware(api_key=os.environ["RUNWARE_API_KEY"]) as client:
results = await client.run({
"model": "prunaai:p-video@upscale",
"deliveryMethod": "async",
"resolution": "4k",
"inputs": {
"video": "8b9c0d1e-2f3a-4b5c-9d6e-7f8a9b0c1d2e"
}
})
asyncio.run(main())curl https://api.runware.ai/v1 \
-H "Authorization: Bearer $RUNWARE_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"taskType": "upscale",
"taskUUID": "5d7f9b1c-3e5a-4c7e-9a1b-2d4f6a8c0e3f",
"model": "prunaai:p-video@upscale",
"deliveryMethod": "async",
"resolution": "4k",
"inputs": {
"video": "8b9c0d1e-2f3a-4b5c-9d6e-7f8a9b0c1d2e"
}
}
]'runware run prunaai:p-video@upscale \
deliveryMethod=async \
resolution=4k \
inputs.video=8b9c0d1e-2f3a-4b5c-9d6e-7f8a9b0c1d2e{
"taskType": "upscale",
"taskUUID": "5d7f9b1c-3e5a-4c7e-9a1b-2d4f6a8c0e3f",
"model": "prunaai:p-video@upscale",
"deliveryMethod": "async",
"resolution": "4k",
"inputs": {
"video": "8b9c0d1e-2f3a-4b5c-9d6e-7f8a9b0c1d2e"
}
}Response
[
{
"taskType": "upscale",
"taskUUID": "5d7f9b1c-3e5a-4c7e-9a1b-2d4f6a8c0e3f",
"videoUUID": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f",
"videoURL": "https://vm.runware.ai/video/os/a14d18/ws/2/vi/c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f.mp4"
}
]The upscale keeps the shape and the soundtrack of the render. The 1344 × 768 clip came back at 3808 × 2176, the 4K pixel budget for that shape, with the audio P-Video-2-Pro generated carried over unchanged.
Fitting a 4K finish
At 4k the model processes at most 300 frames, and P-Video-2-Pro returns a clip near the duration you ask for rather than exactly on it. Both matter when you plan a 4K finish, because the margin is small.
duration | Frames returned at 24 fps | 4k at the source rate | 4k at 30 or 60 fps |
|---|---|---|---|
5 | 124 | Fits | Fits |
8 | 192 | Fits | Fits |
10 | 243 | Fits | Rejected, 304 frames |
15 | about 345 | Rejected | Rejected |
At the source rate every render up to 10 seconds fits. Raise the frame rate on the same pass and the frames are counted at 30 per second, so a 10-second render, which comes back at 10.125 seconds, lands at 304 frames and is rejected. Keep 4K renders at 8 seconds or less when you also ask for 30 or 60 fps, and send 15-second renders to 2k, which takes them at any rate. Frame rates are covered in raising the frame rate.
Rendering at 480p or 768p
A 1080p finish can start from either P-Video-2-Pro tier, so the choice is where the detail comes from: the render or the upscale. The two takes below are quality renders of one prompt on one seed with the expander off. One rendered at 640 × 480, the other at 1024 × 768, and both were upscaled to 1080p.
A slow gimbal push into a bright boutique hotel room as sheer white curtains drift in the breeze, a king bed with crisp white linen and a woven rattan headboard, a terracotta tiled floor, a pair of cane armchairs by open glass doors, and a balcony beyond with a view of the sea. Soft morning daylight, crisp detail in the linen weave, the rattan and the tiles. Photoreal hospitality marketing video, smooth steady forward motion, no text, no logos, no people. Audio: a light sea breeze, distant waves, no music.
A slow gimbal push into a bright boutique hotel room as sheer white curtains drift in the breeze, a king bed with crisp white linen and a woven rattan headboard, a terracotta tiled floor, a pair of cane armchairs by open glass doors, and a balcony beyond with a view of the sea. Soft morning daylight, crisp detail in the linen weave, the rattan and the tiles. Photoreal hospitality marketing video, smooth steady forward motion, no text, no logos, no people. Audio: a light sea breeze, distant waves, no music.
They are two different rooms. On this prompt the seed did not carry the take across tiers: the 480p render kept the armchairs inside by narrow glass doors, and the 768p render opened the wall into sliding doors with the chairs out on the balcony. So the tier is part of the take, and a shot you pick at 480p is the shot you deliver, upscaled, rather than one you can render again at 768p. Changing mode starts a new take as well, as the P-Video-2-Pro guide to speed, quality and size covers.
Compare texture rather than framing, and both upscales hold up at 1080p. The cane on the headboards and the armchairs reads as woven in both, and the 768p take keeps the finer, crisper weave, because it started with more of it. The 480p route costs close to half per rendered second and finishes a little softer at 100%, which is a fair trade for a feed and a poor one for a hero shot.
Tips
-
Pass the
videoUUIDalong. The upscale takes it directly ininputs.video, so there is nothing to download and upload between the two requests. -
Plan 4K renders at 10 seconds or less. Drop to 8 if the same pass raises the frame rate, and send longer renders to
2k. -
Pick the shot at the tier and in the mode you deliver in. The same seed came back as a different take at 480p and at 768p here, and a change of mode starts a new take too.
-
Upscale once, to the size you deliver. A 1080p feed does not need a 4K pass, and the 4K cap is the tightest on length.
-
Raise the frame rate on the same pass.
fpsgoes in the upscale request, so a 24 fps render can come back at 30 or 60 without a third step. See raising the frame rate.