Concatenate Videos
January 29, 2026 (September 2, 2026)
Table of contents
Concatenate multiple previously generated videos into a single video. This is a synchronous operation that returns base64-encoded video data.
- Combines 2-10 videos into a single video file.
- Each clip contributes its full recorded length: 8 seconds for a standard Veo clip, 4 or 6 seconds for the short Veo durations, and up to 10 seconds for an Omni 1.1 Flash edit. Earlier versions cut every clip at 8 seconds, which silently dropped the last 2 seconds of each 10-second Omni clip.
- All videos must have the same aspect ratio (all landscape or all portrait).
- No captcha required - this endpoint doesn’t require reCAPTCHA solving.
- Optional trimming allows removing frames from the start/end of each video for smoother transitions.
- Returns large base64-encoded video data (~7MB per input video).
- Concatenation typically completes within 15-20 seconds.
https://api.useapi.net/v1/google-flow/videos/concatenate
Request Headers
Authorization: Bearer {API token}
Content-Type: application/json
API tokenis required, see Setup useapi.net for details.
Request Body
{
"media": [
{ "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx..." },
{ "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMy...", "trimStart": 0.5 },
{ "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMz...", "trimEnd": 1 }
]
}
mediais required. Array of 2-10 video references to concatenate. Each item contains:mediaGenerationIdis required. ThemediaGenerationIdfrom a previously generated or extended video.trimStartis optional. Seconds to trim from the start of this video (0-10, default: 0). When concatenating extended videos, usetrimStart: 1to remove the ~1 second overlap with the source video.trimEndis optional. Seconds to trim from the end of this video (0-10, default: 0).trimStartplustrimEndmust be less than the clip’s own length, otherwise the request returns400.- Clips from POST /videos/upscale can be joined too, and the output keeps their resolution. Google records no length on an upscaled clip, so its length is taken from the clip it was upscaled from.
Notes:
- All videos must belong to the same Google Flow account (same email).
- All videos must have the same aspect ratio.
- Videos are concatenated in the order provided.
- Omni 1.1 Flash edits chained from one source all re-render the same time window, so joining them repeats the source motion with each edit applied. See the video reference notes on POST /videos.
Responses
-
Videos concatenated successfully. Returns job ID and base64-encoded video data.
{ "jobId": "j1737312345678v-u12345-email:jo***@gmail.com-bot:google-flow", "status": "MEDIA_GENERATION_STATUS_SUCCESSFUL", "inputsCount": 3, "encodedVideo": "AAAAIGZ0eXBpc29t...~21MB base64..." } -
Invalid request.
{ "error": "Error message", "code": 400 } -
Invalid API token.
{ "error": "Unauthorized" } -
Account not found or video not found.
{ "error": "Google Flow account [email protected] not found" } -
Concatenation polling timeout (after 3 minutes).
{ "error": "Polling timeout" }
Model
{
jobId: string // Job identifier
status: string // MEDIA_GENERATION_STATUS_SUCCESSFUL | FAILED
inputsCount: number // Number of input videos
encodedVideo: string // Base64-encoded MP4 (~7MB per input, decode and save as .mp4)
error?: string | { // Error: string (useapi.net) or object (Google API)
code: number
message: string
status: string
details?: Array<{
'@type': string
reason: string
}>
}
}
Examples
-
# Generate first video curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "A serene mountain landscape at sunrise"}' \ "https://api.useapi.net/v1/google-flow/videos" > video1.json # Generate second video (or extend the first) curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "The sun rises higher, birds fly across the sky"}' \ "https://api.useapi.net/v1/google-flow/videos" > video2.json # Extract mediaGenerationIds VIDEO1_ID=$(jq -r '.media[0].mediaGenerationId' video1.json) VIDEO2_ID=$(jq -r '.media[0].mediaGenerationId' video2.json) # Concatenate videos curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"media\": [{\"mediaGenerationId\": \"$VIDEO1_ID\"}, {\"mediaGenerationId\": \"$VIDEO2_ID\", \"trimStart\": 0.5}]}" \ "https://api.useapi.net/v1/google-flow/videos/concatenate" > concat.json # Decode base64 and save as MP4 jq -r '.encodedVideo' concat.json | base64 -d > concatenated_video.mp4 -
const token = 'YOUR_API_TOKEN'; // Assume you have two video mediaGenerationIds const videoId1 = 'user:12345-email:6a6f...-video:CAMaJDMx...'; const videoId2 = 'user:12345-email:6a6f...-video:CAMaJDMy...'; // Concatenate videos const concatResponse = await fetch('https://api.useapi.net/v1/google-flow/videos/concatenate', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ media: [ { mediaGenerationId: videoId1 }, { mediaGenerationId: videoId2, trimStart: 0.5 } // Trim 0.5s from start for smooth transition ] }) }); const result = await concatResponse.json(); // Decode base64 and save (Node.js) const buffer = Buffer.from(result.encodedVideo, 'base64'); require('fs').writeFileSync('concatenated_video.mp4', buffer); console.log('Concatenated video saved!'); // Or use in browser as data URL for preview const dataUrl = `data:video/mp4;base64,${result.encodedVideo}`; document.getElementById('video-player').src = dataUrl; -
import requests import base64 token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } # Assume you have two video mediaGenerationIds video_id_1 = 'user:12345-email:6a6f...-video:CAMaJDMx...' video_id_2 = 'user:12345-email:6a6f...-video:CAMaJDMy...' # Concatenate videos concat_response = requests.post( 'https://api.useapi.net/v1/google-flow/videos/concatenate', headers=headers, json={ 'media': [ {'mediaGenerationId': video_id_1}, {'mediaGenerationId': video_id_2, 'trimStart': 0.5} # Trim 0.5s for smooth transition ] } ) result = concat_response.json() # Decode base64 and save video_data = base64.b64decode(result['encodedVideo']) with open('concatenated_video.mp4', 'wb') as f: f.write(video_data) print(f'Concatenated video saved! ({len(video_data)} bytes)')