Claude-code-plugins klingai-video-extension
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/klingai-pack/skills/klingai-video-extension" ~/.claude/skills/jeremylongshore-claude-code-plugins-klingai-video-extension && rm -rf "$T"
manifest:
plugins/saas-packs/klingai-pack/skills/klingai-video-extension/SKILL.mdsource content
Kling AI Video Extension
Overview
Extend an existing video by appending additional seconds. The extension endpoint takes the
task_id of a completed video and generates a seamless continuation.
Endpoint:
POST https://api.klingai.com/v1/videos/video-extend
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | Task ID of the completed source video |
| string | No | Motion/scene description for extension |
| string | No | Extension length: (default) |
| string | No | or |
| string | No | Default: |
| string | No | Webhook for completion |
Basic Extension
import jwt, time, os, requests BASE = "https://api.klingai.com/v1" def get_headers(): ak, sk = os.environ["KLING_ACCESS_KEY"], os.environ["KLING_SECRET_KEY"] token = jwt.encode( {"iss": ak, "exp": int(time.time()) + 1800, "nbf": int(time.time()) - 5}, sk, algorithm="HS256", headers={"alg": "HS256", "typ": "JWT"} ) return {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} # Step 1: Generate the initial 5s video initial = requests.post(f"{BASE}/videos/text2video", headers=get_headers(), json={ "model_name": "kling-v2-master", "prompt": "A rocket launching from a desert landscape, cinematic", "duration": "5", "mode": "standard", }).json() initial_task_id = initial["data"]["task_id"] # Wait for completion... # (poll until task_status == "succeed") # Step 2: Extend by 5 more seconds extension = requests.post(f"{BASE}/videos/video-extend", headers=get_headers(), json={ "task_id": initial_task_id, "prompt": "The rocket ascends through clouds into the stratosphere", "duration": "5", "mode": "standard", }).json() ext_task_id = extension["data"]["task_id"] # Step 3: Poll extension task while True: time.sleep(15) result = requests.get( f"{BASE}/videos/video-extend/{ext_task_id}", headers=get_headers() ).json() if result["data"]["task_status"] == "succeed": extended_url = result["data"]["task_result"]["videos"][0]["url"] print(f"Extended video: {extended_url}") break elif result["data"]["task_status"] == "failed": print(f"Failed: {result['data']['task_status_msg']}") break
Chain Multiple Extensions
def chain_extensions(initial_task_id: str, prompts: list[str], duration: str = "5", mode: str = "standard") -> list[str]: """Chain multiple extensions to build a longer video.""" current_task_id = initial_task_id video_urls = [] for i, prompt in enumerate(prompts): print(f"Extension {i + 1}/{len(prompts)}: submitting...") # Submit extension r = requests.post(f"{BASE}/videos/video-extend", headers=get_headers(), json={ "task_id": current_task_id, "prompt": prompt, "duration": duration, "mode": mode, }).json() ext_task_id = r["data"]["task_id"] # Poll for completion while True: time.sleep(15) result = requests.get( f"{BASE}/videos/video-extend/{ext_task_id}", headers=get_headers() ).json() status = result["data"]["task_status"] if status == "succeed": url = result["data"]["task_result"]["videos"][0]["url"] video_urls.append(url) current_task_id = ext_task_id # next extension chains from this print(f"Extension {i + 1} complete: {url}") break elif status == "failed": raise RuntimeError(f"Extension {i + 1} failed: {result['data']['task_status_msg']}") return video_urls
Usage: Build a 20-Second Video
# Generate initial 5s initial_r = requests.post(f"{BASE}/videos/text2video", headers=get_headers(), json={ "model_name": "kling-v2-master", "prompt": "Morning sunrise over a mountain lake, mist rising", "duration": "5", "mode": "standard", }).json() initial_id = initial_r["data"]["task_id"] # ... poll until complete ... # Chain 3 more extensions = 5 + 5 + 5 + 5 = 20 seconds total extensions = chain_extensions(initial_id, [ "Sun rises higher, birds begin flying across the lake", "A deer approaches the water's edge to drink", "Wide shot pulling back to reveal the full mountain range", ])
Cost
Each extension costs the same as a new generation:
| Extension Duration | Standard | Professional |
|---|---|---|
| 5 seconds | 10 credits | 35 credits |
A 20-second video (initial + 3 extensions) costs 40 credits in standard mode.
Error Handling
| Error | Cause | Fix |
|---|---|---|
Invalid | Source task doesn't exist | Verify task_id is from a completed generation |
| Source not complete | Extending a task still processing | Wait for source task to reach status |
| Extension failed | Prompt conflict with source | Align extension prompt with original scene |