Skip to main content

Python client library for Kdenlive JSON-RPC API

Project description

kdenlive-api

Python client library for the Kdenlive JSON-RPC WebSocket API.

Installation

pip install kdenlive-api

Or with uv:

uv add kdenlive-api

Requirements

  • Python 3.11+
  • Kdenlive with RPC server enabled (requires kdenlive-websocket fork)

Quick Start

import asyncio
from kdenlive_api import KdenliveClient

async def main():
    async with KdenliveClient() as client:
        # Get project info
        info = await client.project.get_info()
        print(f"Project: {info.name}")
        print(f"Resolution: {info.width}x{info.height}")
        print(f"FPS: {info.fps}")

        # List clips in bin
        clips = await client.bin.list_clips()
        for clip in clips:
            print(f"  - {clip.name}")

        # Get timeline info
        timeline = await client.timeline.get_info()
        print(f"Timeline duration: {timeline.duration} frames")

asyncio.run(main())

Examples

The examples/ directory contains 15 ready-to-use scripts solving common video editing problems:

Script Problem Solved
01_batch_import_organize.py Import and auto-organize files by type
02_quick_rough_cut.py Add clips to timeline in order
03_auto_transitions.py Add transitions between all clips
04_batch_color_grade.py Apply consistent color correction
05_add_fade_effects.py Add fade-in/fade-out effects
06_trim_silence.py Trim dead air from clips
07_track_setup.py Create organized track structure
08_multi_format_export.py Export for multiple platforms
09_scene_splitter.py Split clips at intervals
10_cleanup_timeline.py Remove tiny leftover clips
11_backup_project.py Auto-save with timestamps
12_apply_preset_effects.py Apply saved effect presets
13_audio_ducking_setup.py Lower music during speech
14_marker_based_export.py Export by guide markers
15_project_template.py Create projects from templates

All scripts accept command-line arguments. Run with --help for usage:

python examples/01_batch_import_organize.py --help

Configuration

Environment Variables

Variable Description Default
KDENLIVE_WS_URL WebSocket URL ws://localhost:9876
KDENLIVE_AUTH_TOKEN Bearer token for authentication None

Programmatic Configuration

from kdenlive_api import KdenliveClient

# Custom URL
client = KdenliveClient(url="ws://192.168.1.100:9876")

# With authentication
client = KdenliveClient(auth_token="your-secret-token")

# Both
client = KdenliveClient(
    url="ws://192.168.1.100:9876",
    auth_token="your-secret-token"
)

API Namespaces

The client provides access to Kdenlive functionality through typed API namespaces:

Project (client.project)

# Get project information
info = await client.project.get_info()

# Open a project
await client.project.open("/path/to/project.kdenlive")

# Save project
await client.project.save()
await client.project.save("/path/to/new-project.kdenlive")

# Create new project
await client.project.new(profile="atsc_1080p_25")

# Close project
await client.project.close(save_changes=True)

# Undo/Redo
await client.project.undo()
await client.project.redo()

Timeline (client.timeline)

# Get timeline info
info = await client.timeline.get_info()

# Get all tracks
tracks = await client.timeline.get_tracks()

# Get clips (all or by track)
clips = await client.timeline.get_clips()
clips = await client.timeline.get_clips(track_id=0)

# Insert clip from bin
clip_id = await client.timeline.insert_clip(
    bin_clip_id="abc123",
    track_id=0,
    position=100  # frames
)

# Move clip
await client.timeline.move_clip(clip_id=1, track_id=1, position=200)

# Delete clip
await client.timeline.delete_clip(clip_id=1)

# Split clip
parts = await client.timeline.split_clip(clip_id=1, position=50)

# Resize/trim clip
await client.timeline.resize_clip(clip_id=1, in_point=10, out_point=100)

# Track management
track_id = await client.timeline.add_track("video", name="V3")
await client.timeline.delete_track(track_id=2)

# Playhead
await client.timeline.seek(position=500)
position = await client.timeline.get_position()

Bin (client.bin)

# List clips and folders
clips = await client.bin.list_clips()
clips = await client.bin.list_clips(folder_id="folder123")
folders = await client.bin.list_folders()

# Get clip details
info = await client.bin.get_clip_info(clip_id="abc123")

# Import media
clip_id = await client.bin.import_clip("/path/to/video.mp4")
clip_ids = await client.bin.import_clips([
    "/path/to/video1.mp4",
    "/path/to/video2.mp4"
], folder_id="folder123")

# Organize
folder_id = await client.bin.create_folder("Footage", parent_id=None)
await client.bin.rename_item(item_id="abc123", name="New Name")
await client.bin.move_item(item_id="abc123", target_folder_id="folder123")
await client.bin.delete_clip(clip_id="abc123")

# Markers
marker_id = await client.bin.add_clip_marker(
    clip_id="abc123",
    position=100,
    comment="Important moment"
)
await client.bin.delete_clip_marker(clip_id="abc123", marker_id=0)

Effects (client.effects)

# List available effects
effects = await client.effects.list_available()

# Get effect details
info = await client.effects.get_info(effect_id="blur")

# Apply effect to clip
instance_id = await client.effects.add(effect_id="blur", clip_id=1)

# Get effects on a clip
clip_effects = await client.effects.get_clip_effects(clip_id=1)

# Modify effect parameters
await client.effects.set_property(
    clip_id=1,
    effect_id="effect123",
    property_name="radius",
    value=10.5
)

# Enable/disable effects
await client.effects.enable(clip_id=1, effect_id="effect123")
await client.effects.disable(clip_id=1, effect_id="effect123")

# Remove effect
await client.effects.remove(clip_id=1, effect_id="effect123")

# Keyframes
keyframes = await client.effects.get_keyframes(
    clip_id=1,
    effect_id="effect123",
    property_name="radius"
)

await client.effects.set_keyframe(
    clip_id=1,
    effect_id="effect123",
    property_name="radius",
    position=50,
    value=20.0
)

await client.effects.delete_keyframe(
    clip_id=1,
    effect_id="effect123",
    property_name="radius",
    position=50
)

Render (client.render)

# Get available presets
presets = await client.render.get_presets()

# Start render
job = await client.render.start(
    preset_name="MP4-H264",
    output_path="/path/to/output.mp4"
)

# Monitor progress
status = await client.render.get_status(job_id=job.job_id)
print(f"Progress: {status.progress}%")

# Get all jobs
jobs = await client.render.get_jobs()
active = await client.render.get_active_job()

# Stop render
await client.render.stop(job_id=job.job_id)

Assets (client.asset)

# Browse categories
categories = await client.asset.list_categories()

# Search
results = await client.asset.search("blur")

# Get effects by category
effects = await client.asset.get_effects_by_category("Color")

# Favorites
favorites = await client.asset.get_favorites()
await client.asset.add_favorite(asset_id="blur")
await client.asset.remove_favorite(asset_id="blur")

# Presets
presets = await client.asset.get_presets(effect_id="blur")
await client.asset.save_preset(effect_id="blur", preset_name="My Blur")

Transitions (client.transition)

# List available transitions
transitions = await client.transition.list()

# Add transition between clips
info = await client.transition.add(
    transition_type="dissolve",
    from_clip_id=1,
    to_clip_id=2
)

# Remove transition
await client.transition.remove(transition_id=info.id)

Compositions (client.composition)

# List compositions
compositions = await client.composition.list()

# Add composition
info = await client.composition.add(
    composition_type="composite",
    track=0,
    position=100
)

# Remove composition
await client.composition.remove(composition_id=info.id)

Notifications

Subscribe to real-time notifications from Kdenlive:

async def handle_notification(method: str, params: dict):
    if method == "render.progress":
        print(f"Render progress: {params['progress']}%")
    elif method == "timeline.changed":
        print("Timeline was modified")

client = KdenliveClient()
client.on_notification(handle_notification)
await client.connect()

Error Handling

from kdenlive_api import (
    KdenliveError,
    ConnectionError,
    ProjectNotOpenError,
    ClipNotFoundError,
    ValidationError,
)

try:
    await client.project.get_info()
except ConnectionError:
    print("Cannot connect to Kdenlive")
except ProjectNotOpenError:
    print("No project is open")
except ClipNotFoundError as e:
    print(f"Clip not found: {e}")
except ValidationError as e:
    print(f"Invalid parameters: {e}")
except KdenliveError as e:
    print(f"Kdenlive error: {e}")

Type Safety

All API responses are typed using Pydantic models:

from kdenlive_api import ProjectInfo, ClipInfo, TimelineClip

info: ProjectInfo = await client.project.get_info()
print(info.width)  # IDE autocomplete works!

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kdenlive_api-0.2.0.tar.gz (18.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kdenlive_api-0.2.0-py3-none-any.whl (24.8 kB view details)

Uploaded Python 3

File details

Details for the file kdenlive_api-0.2.0.tar.gz.

File metadata

  • Download URL: kdenlive_api-0.2.0.tar.gz
  • Upload date:
  • Size: 18.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.11

File hashes

Hashes for kdenlive_api-0.2.0.tar.gz
Algorithm Hash digest
SHA256 db684ad827b7f9423da8fefe2b2643803e5a83cc0bffa9fb8861955e4146980a
MD5 d3c7e178a189ad4a31aa9a55b2ed2cd0
BLAKE2b-256 d76e8fd1e4247c4640c2c1c49cb564f5d8ba99d643779815336071cf973a7c39

See more details on using hashes here.

File details

Details for the file kdenlive_api-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for kdenlive_api-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e5c3efdd5b36babc092d0b14c91ed92f9e88a57c21f429a086dab97fc1d05cff
MD5 bc19185b08459454d52b066bda25743a
BLAKE2b-256 1d3b975205aeb6c2b40f5907fa07381d771e5dd4ff53a080167b3ea9595956bf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page