.. Copyright (c) 2026 OpenShot Studios, LLC. GPL-3.0-or-later. .. _cli_ref: Command Line Interface ====================== Bring OpenShot into your command-line workflow. Import footage, trim and arrange clips, apply effects, animate properties with keyframes, and export videos from your terminal. Use a few commands to automate repetitive edits, write a script for a recurring project, or let an AI agent help assemble and refine a video. The command line works with the same projects as the editor. You can control an open editor and review changes as you go, or work in a **headless session** without opening a window. A session keeps your project open between commands, including its edits, undo history, and export jobs. Save it as an ``.osp`` project whenever you want to continue editing later. Getting started --------------- Use your installed OpenShot executable followed by ``--cli``. Start with ``intro`` for a short guide to sessions, editing, animation, and saving, or ``help`` for the command overview. These commands do not need an active session. The examples below require an OpenShot build that includes command-line editing. .. _cli_appimage_ref: Linux AppImage ~~~~~~~~~~~~~~ From the directory containing your downloaded AppImage:: ./OpenShot.AppImage --cli intro ./OpenShot.AppImage --cli help Replace ``OpenShot.AppImage`` with your downloaded filename. If **AppImageLauncher** shows desktop integration dialogs, set ``APPIMAGELAUNCHER_DISABLE=1`` before launching the command:: APPIMAGELAUNCHER_DISABLE=1 ./OpenShot.AppImage --cli intro For scripts or repeated commands, set it once in your current shell:: export APPIMAGELAUNCHER_DISABLE=1 ./OpenShot.AppImage --cli session start The variable must be set before launching the AppImage: AppImageLauncher can intercept it before OpenShot receives ``--cli``. Relative media paths and ``@batch.json`` files are resolved from your working directory. Keep the AppImage file available while its sessions or exports are running. Linux Snap ~~~~~~~~~~ For the `OpenShot Snap `_, use:: snap run openshot-qt --cli intro snap run openshot-qt --cli help snap run openshot-qt --cli session start Snap's file permissions apply to command-line editing too. Keep media, projects, and exports in locations the Snap can access, such as your home folder. To allow access to external drives, connect the removable-media permission:: sudo snap connect openshot-qt:removable-media Windows ~~~~~~~ .. important:: **Use openshot-qt-cmd.exe for command-line editing on Windows.** This console executable displays command results, help, and errors in your terminal. The desktop executable, ``openshot-qt.exe``, does not display standard output in an interactive terminal, leaving commands without visible feedback and making the CLI difficult to use. In PowerShell, from the OpenShot installation directory:: & .\openshot-qt-cmd.exe --cli intro & .\openshot-qt-cmd.exe --cli help & .\openshot-qt-cmd.exe --cli session start If you are in a different directory, use the full path to ``openshot-qt-cmd.exe``. Keep ``--cli`` after the executable name. macOS ~~~~~ For an installation in Applications:: "/Applications/OpenShot Video Editor.app/Contents/MacOS/openshot-qt" --cli intro "/Applications/OpenShot Video Editor.app/Contents/MacOS/openshot-qt" --cli help Finding commands ---------------- Throughout this guide, ``openshot-cli`` is shorthand for your installation's command above, such as ``snap run openshot-qt --cli`` or ``./OpenShot.AppImage --cli``. Some installations also provide an ``openshot-cli`` command directly. When running from source, use ``python3 src/launch.py --cli`` in OpenShot's Python environment. Bare ``--cli``, ``--cli help``, and ``--cli --help`` show the same overview. Help becomes more specific as you navigate commands:: openshot-cli clip help openshot-cli clip keyframe help openshot-cli clip keyframe set help openshot-cli edit help openshot-cli text help openshot-cli effects list openshot-cli effects audiovisualization help openshot-cli effects audiovisualization help --property background Group help explains workflows with examples; operation help describes arguments and behavior. ``--help`` is equivalent to trailing ``help``. All help commands work without an editing session. ``effects list`` shows the available effects with short descriptions. Effect help explains their properties, defaults, choices, and ranges. ``effects instances`` lists effects already attached to clips, with parent clip IDs. Class names, display names, and underscore aliases identify the same effect. Working with scripts and AI agents ---------------------------------- AI coding agents such as **Codex** and **Claude Code** can use the CLI to inspect and edit OpenShot projects through terminal commands. Give your agent the path to your OpenShot executable, the media or project to work with, and the desired result: duration, dimensions, animation style, and output location. Ask it to read ``--cli intro`` before starting. The same commands work when you type them yourself or run them from a script. Start with ``intro``, then use command-specific help as needed. A useful workflow is to select a session, inspect the project, make a small set of changes, review the result, and save. Commands return structured JSON so scripts and agents can use object IDs and results directly instead of interpreting screen output. * **Inspect before editing.** Use returned IDs and property information instead of guessing names, track numbers, or timing. Select a session explicitly when more than one project is open. * **Group repeated edits.** Use ``edit apply`` for a sequence of changes or ``edit bulk`` to apply a template to selected clips. Validate with ``--dry-run`` before applying a batch. * **Check animation.** Choose a coordinate space, start with a few keyframes, and use easing presets for familiar motion. ``keyframe preview`` samples the curve so you can spot pauses or jumps before exporting. Review rendered motion as well; a contact sheet alone cannot show how an animation feels. * **Save and follow exports.** Save the project explicitly and check the export job's status before treating an output as complete. If a request times out, inspect its status before repeating an edit. The sections below explain these workflows and their timing conventions. Sessions and outputs -------------------- Starting or finding a session ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Start one headless session (without an editor window):: openshot-cli session start To open an existing project at startup, add ``--project "/path/project.osp"``. The successful JSON response contains ``result.session_id``. Copy that value. If OpenShot is already running, or you have forgotten the ID, find available sessions with:: openshot-cli session list Choose the session for the project you intend to edit. You do not need to start a new session for each command. .. _cli_session_selection_ref: Selecting a session ~~~~~~~~~~~~~~~~~~~ .. tip:: **Set OPENSHOT_SESSION once, then run commands normally.** Your terminal remembers the selected session, so you do not need to pass ``--session`` with every command. Use the PowerShell or Bash example below. Replace ``SESSION_ID`` below with the ``session_id`` returned by ``session start`` or ``session list``. Windows PowerShell:: $env:OPENSHOT_SESSION = "SESSION_ID" & .\openshot-qt-cmd.exe --cli timeline view & .\openshot-qt-cmd.exe --cli export start "C:\path\test.mp4" --wait Linux Bash:: export OPENSHOT_SESSION="SESSION_ID" ./OpenShot.AppImage --cli timeline view ./OpenShot.AppImage --cli export start "/path/test.mp4" --wait On macOS, use the same ``export`` syntax. For macOS or Snap commands, substitute your installation's executable from Getting started. The selection lasts for this terminal and commands launched from it. Set it again in a new terminal, or update it when switching to a different session. **The remaining editing and export examples assume OPENSHOT_SESSION is set.** The next subsection shows how to capture the ID automatically for scripts. To target a different session for just one command, use ``--session``. It overrides ``OPENSHOT_SESSION`` without changing your terminal's selection:: openshot-cli --session OTHER_SESSION_ID project get With a packaged executable, put this override after ``--cli`` and before the command group: ``--cli --session OTHER_SESSION_ID project get``. Automatic selection only works when exactly one reachable session exists. If you see ``session_required``, run ``session list`` and explicitly select the intended session. If it is no longer listed, start it again and use the new ID. Help, ``intro``, and session discovery do not require a selected session. Capturing the session ID automatically ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Scripts can read ``result.session_id`` directly from the JSON returned by ``session start`` and set ``OPENSHOT_SESSION`` for subsequent commands. There is no need to copy the ID manually or read a log file. Check that startup succeeded before using the returned ID. Windows PowerShell (set the executable path for your installation):: $openshot = "C:\Program Files\OpenShot Video Editor\openshot-qt-cmd.exe" $reply = & $openshot --cli session start if ($LASTEXITCODE -ne 0) { throw "OpenShot session startup failed" } $session = $reply | ConvertFrom-Json if (-not $session.ok -or -not $session.result.session_id) { throw "OpenShot did not return a session ID" } $env:OPENSHOT_SESSION = $session.result.session_id & $openshot --cli timeline view Linux Bash (requires ``jq`` to read JSON):: openshot="/full/path/to/OpenShot.AppImage" export APPIMAGELAUNCHER_DISABLE=1 if reply=$("$openshot" --cli session start) && session_id=$(printf '%s' "$reply" | jq -er 'select(.ok == true) | .result.session_id | strings | select(length > 0)'); then export OPENSHOT_SESSION="$session_id" "$openshot" --cli timeline view else echo "OpenShot session startup failed" >&2 fi The environment variable selects a session for commands launched from this terminal; it does not change a system-wide setting. Starting a session does not set the variable automatically. After stopping the session, clear the selection with ``Remove-Item Env:OPENSHOT_SESSION`` in PowerShell or ``unset OPENSHOT_SESSION`` in Bash. Showing and stopping a session ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To show the selected session in the editor:: openshot-cli session show On a desktop, ``session show`` creates the editor in the same process and keeps the live project, IDs, history, export jobs, and connection. Repeated calls raise the existing window. ``session start --show`` opens it immediately. Sessions started without a display, or with ``QT_QPA_PLATFORM=offscreen``/``minimal``, cannot later show a desktop window. For those sessions, save and open the project in a new desktop session. Once shown, close the session through the editor window. Global options (``--session``, ``--timeout``) go before the command. ``session serve`` stays in the foreground for supervisors; ``session start`` returns after a background host registers. ``session stop`` refuses unsaved changes and active exports. Use ``--discard`` only to intentionally discard unsaved edits. Command output ~~~~~~~~~~~~~~ Results are JSON on stdout, except the default text timeline view. Errors are JSON on stderr with exit status 1; argument-parser errors exit 2. Mutations return compact summaries with an ``inspect`` command. ``get`` returns native object JSON. Project replies include a revision; effect catalog replies do not require a session. Logs from headless sessions live beside their registry records. ``OPENSHOT_SESSION_DIR`` overrides the default ``~/.openshot_qt/sessions`` directory. Sessions accept commands locally on your computer. Keep the session registry private, since it contains the credentials used to access your editing sessions. Exports work from a snapshot, so you can continue editing while a job runs. Opening and saving projects --------------------------- An OpenShot project (``.osp``) stores your editable timeline. Exporting creates a finished video; saving the project lets you return to its clips, effects, and keyframes later. Save your project separately even when you also export a video. Opening a project ~~~~~~~~~~~~~~~~~ Start a session with an existing project:: openshot-cli session start --project "/home/me/Videos/My Project.osp" Add ``--show`` to open its editor window too. To use an editor that is already running, find it with ``session list``. Set ``OPENSHOT_SESSION`` to its returned session ID, then open or inspect a project:: openshot-cli project open "/home/me/Videos/My Project.osp" openshot-cli project get Replace the example path with your own, and quote paths containing spaces. ``project open`` replaces the selected session's current project. It refuses to discard unsaved edits unless you explicitly add ``--discard``; save those edits first if you want to keep them. Opening through the CLI does not show interactive missing-media dialogs, so keep the project's source media available. For a new, empty project, use ``session start`` without ``--project``, then import media and add clips as described under Editing. Saving a project or a copy ~~~~~~~~~~~~~~~~~~~~~~~~~~ Save to a new file, or create a separate version before making more changes:: openshot-cli project save "/home/me/Videos/My Project v2.osp" To update an existing file, explicitly allow replacement:: openshot-cli project save "/home/me/Videos/My Project v2.osp" --overwrite Always supply the destination path. Saving an ``.osp`` does not package all your source footage into that file; keep the referenced media available when moving or reopening the project. Exporting a video ----------------- Automate rendering and exporting from scripts or AI agents, using the project's settings or choosing a different output profile for each render. Export jobs can run in the background or wait for completion before your script continues. To render an MP4 using the project's resolution and frame rate:: openshot-cli export start "/home/me/Videos/video.mp4" --wait By default, OpenShot uses H.264 video and AAC audio. Replace the example path with your destination, using an existing folder and a new filename. Existing outputs are never overwritten. Exporting does not save your editable ``.osp`` project; use ``project save`` separately to keep your editing work. The ``--wait`` option keeps the command running until the export completes or reports a failure. Review the finished video before sharing it. Checking export progress ~~~~~~~~~~~~~~~~~~~~~~~~ Leave off ``--wait`` to start an export in the background. The response includes a job ID you can use to check its progress:: openshot-cli export start "/home/me/Videos/video.mp4" openshot-cli export status JOB_ID openshot-cli export status JOB_ID --wait openshot-cli export list Replace ``JOB_ID`` with the returned ID. If waiting times out, the export keeps running; check the same job instead of starting another export. To stop a job, use ``export cancel JOB_ID``. Each job captures the timeline when it starts, so later edits do not change an export already in progress. Waiting defaults to 600 seconds; adjust this with ``--wait-timeout``. This is separate from the global per-request ``--timeout``. Export failures, cancellation, and wait timeouts exit with status 1 and include job details. Exporting in multiple profiles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Export the same timeline at different resolutions or aspect ratios by choosing an export profile for each output. **An export profile applies only to that job**; it does not change the editing project's profile. A profile sets dimensions, frame rate, and aspect ratio; an export preset selects encoding settings such as MP4/H.264. Find the available profiles and inspect their settings:: openshot-cli profile list --search 720 openshot-cli profile list --search 1080 openshot-cli profile get builtin:01280x0720p0030_16-09 For example, export landscape versions at 720p and 1080p, then a square version at 1080 by 1080. These profiles all use 30 fps:: openshot-cli export start "/home/me/Videos/video-720p.mp4" --profile builtin:01280x0720p0030_16-09 --wait openshot-cli export start "/home/me/Videos/video-1080p.mp4" --profile builtin:01920x1080p0030_16-09 --wait openshot-cli export start "/home/me/Videos/video-square.mp4" --profile builtin:01080x1080p0030_01-01 --wait Use a different output filename for each version. Keep edits unchanged between jobs when you want matching versions. Changing aspect ratio can change framing: review each output, especially titles and animated subjects. For a separately composed square or portrait version, save a project copy, change its project profile, and adjust the clips before exporting. See Profiles and the export settings below for custom profiles and encoding options. Batch exporting multiple projects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Reuse one headless session to render several saved projects in sequence. Open a project, export it with ``--wait``, then open the next project. The examples below use each project's own resolution and frame rate and create MP4 files beside the ``.osp`` files. Add ``--profile PROFILE_ID`` to the export command to use one output profile for every project. First run the matching automatic session-ID example above successfully, in the same terminal. It defines ``openshot`` and selects the new session. Replace the project paths below with your own. Use distinct output names that do not already exist; the examples check all destinations before starting the batch. Windows PowerShell:: $projects = @( "C:\VideoProjects\First.osp", "C:\VideoProjects\Second.osp" ) foreach ($project in $projects) { if (-not (Test-Path -LiteralPath $project -PathType Leaf)) { throw "Project not found: $project" } $output = [System.IO.Path]::ChangeExtension($project, ".mp4") if (Test-Path -LiteralPath $output) { throw "Output already exists: $output" } } foreach ($project in $projects) { $output = [System.IO.Path]::ChangeExtension($project, ".mp4") & $openshot --cli project open $project if ($LASTEXITCODE -ne 0) { throw "Could not open: $project" } & $openshot --cli export start $output --wait --wait-timeout 86400 if ($LASTEXITCODE -ne 0) { throw "Export needs attention: $output" } } & $openshot --cli session stop if ($LASTEXITCODE -ne 0) { throw "Could not stop the session" } Remove-Item Env:OPENSHOT_SESSION Linux Bash (the parentheses keep error handling local to the batch):: ( set -e : "${OPENSHOT_SESSION:?Run the session startup example first}" projects=( "/home/me/VideoProjects/First.osp" "/home/me/VideoProjects/Second.osp" ) for project in "${projects[@]}"; do test -f "$project" || { echo "Project not found: $project" >&2; exit 1; } output="${project%.osp}.mp4" test ! -e "$output" || { echo "Output already exists: $output" >&2; exit 1; } done for project in "${projects[@]}"; do "$openshot" --cli project open "$project" "$openshot" --cli export start "${project%.osp}.mp4" --wait --wait-timeout 86400 done "$openshot" --cli session stop ) && unset OPENSHOT_SESSION Both recipes stop the batch on a command failure and leave the session available for inspection. The wait limit here is 24 hours per export. A wait timeout leaves the render running: use ``export list`` and ``export status JOB_ID --wait`` before retrying. Completed videos remain on disk; remove completed projects from the batch before resuming. After resolving a failure, stop the session and clear its environment variable when you are finished. Choosing presets and encoding settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Discover the installed export presets and supported settings:: openshot-cli export preset list openshot-cli export preset get builtin:format_mp4_x264 openshot-cli export capabilities openshot-cli export start /tmp/reel.mp4 --preset builtin:format_mp4_x264 --quality med --wait Export also accepts ``--from-file FILE_ID`` with optional ``--create-custom``. Settings resolve in this order: project defaults, preset, advanced JSON, explicit profile/quality/range flags. Advanced JSON exposes video/audio codecs and bitrate, audio layout/rate/channels, native codec options, hardware device settings, and thread counts. For example, select an encoder option through advanced JSON:: openshot-cli export start /tmp/small.mp4 --profile builtin:00640x0360p0030_16-09 --json '{"video_options":{"preset":"fast"}}' --wait Validating export settings ~~~~~~~~~~~~~~~~~~~~~~~~~~ Check settings before starting a render:: openshot-cli export validate /tmp/reel.mp4 --preset builtin:format_mp4_x264 Capabilities report compiled codec availability, not physical GPU availability. Validation goes further: it opens the encoders (including hardware encoders) and the container with the exact settings, in a separate process, without writing a file. A combination the container can't hold fails with ``incompatible_export``, FFmpeg's own explanation, and the setting to change (``details.cause.path``):: openshot-cli export validate /tmp/song.mp3 --json '{"mode":"audio","format":"mp3","audio_codec":"aac"}' The export worker runs the same check before rendering. Rendering a frame range ~~~~~~~~~~~~~~~~~~~~~~~ Use ``--start-frame`` and ``--end-frame`` to render part of the timeline. Ranges are inclusive and one-based at the **export profile's FPS**. For example, render the first 90 frames at 30 fps (three seconds):: openshot-cli export start /tmp/excerpt.mp4 --profile builtin:01280x0720p0030_16-09 --start-frame 1 --end-frame 90 --wait Audio-only exports and image sequences ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Choose an output mode with advanced JSON:: openshot-cli export start /tmp/music.wav --json '{"mode":"audio","format":"wav","audio_codec":"pcm_s16le"}' --wait openshot-cli export start /tmp/frames --json '{"mode":"image_sequence","format":"png"}' --end-frame 3 --wait Image sequences require a new output directory. Existing outputs are never overwritten. Editing ------- Adding clips and effects ~~~~~~~~~~~~~~~~~~~~~~~~ Use the IDs returned by import/add/list, and discover layer numbers with ``project get``:: openshot-cli file import /absolute/path/video.mp4 openshot-cli clip add FILE_ID --layer 2000000 --position 3 --start 10 --end 17 --volume 0 openshot-cli clip set CLIP_ID --json '{"volume":0.5}' openshot-cli clip keyframe set CLIP_ID --property volume --frame 301 --value 0 openshot-cli clip keyframe set CLIP_ID --property volume --frame 331 --value 1 openshot-cli effects add CLIP_ID saturation openshot-cli effects set EFFECT_ID --json '{"saturation":1.2}' openshot-cli project save /absolute/path/edit.osp Choose the project profile early when possible; populated projects also support profile changes through the existing FPS conversion and undo system. ``--audio-only`` on clip creation suppresses video, including embedded cover art in music files. To use that clip for Audio Visualization instead, enable its video and audio, and follow the effect's help for transparent overlays and layer placement. Understanding clip timing ~~~~~~~~~~~~~~~~~~~~~~~~~ The example keyframes assume a 30fps project and a clip trimmed at source 10s. Position is in timeline seconds; start/end are source seconds, with end exclusive. Frames start at 1. File thumbnail frames use source FPS. Timeline frames use project FPS. Clip keyframes use source coordinates at project FPS, so trimming the clip does not move its first visible keyframe to frame 1. Changing properties ~~~~~~~~~~~~~~~~~~~ ``set`` merges top-level properties. Scalars turn keyframed properties into constants. A supplied nested curve replaces that curve; use ``keyframe set`` to change just one point. JSON arguments accept inline JSON, ``@file.json``, or ``-`` for stdin. Property names, types, enums, keyframes, references, and timing are validated before editing the project. Errors identify the field, expected value, received value, and a correction where possible. GUI slider ranges are advisory where the engine supports values beyond them. Adding fades ~~~~~~~~~~~~ ``clip fade ID --in 0.5 --out 0.5`` calculates source-trim keyframe coordinates automatically. It replaces the alpha curve; ``--property volume --value 0.25`` instead creates an audio fade with a 0.25 peak gain. Durations must fit between the first and last visible frames; fade-out reaches zero on the last frame. Splitting clips ~~~~~~~~~~~~~~~ ``clip split ID --at 6.5`` uses timeline seconds, snaps to the nearest project frame, and keeps both halves. It retains source-coordinate curves and duplicates effects with fresh IDs on the right half, following the editor's slicing behavior. The left half retains its ID. The response reports requested/actual split times and both summaries; a named batch result supports ``{"$ref":"cut.right.id"}``. Splits reject endpoints and locked tracks. Undo restores the original clip in one transaction. Clip menu presets ~~~~~~~~~~~~~~~~~ The editor's clip menu presets use the same code from the command line. Each command lists its presets in its help, and each one is a single undo step: .. code-block:: bash openshot-cli clip motion CLIP_ID --preset slide-in-left openshot-cli clip motion CLIP_ID --preset pulse --at 4.5 openshot-cli clip look CLIP_ID --effect ColorGrade --preset warm_up openshot-cli clip look CLIP_ID --effect all --preset none openshot-cli clip speed CLIP_ID --mode forward --factor 2 openshot-cli clip speed CLIP_ID --mode freeze --at 3 --duration 2 openshot-cli clip repeat CLIP_ID --passes 3 --pattern pingpong openshot-cli clip waveform CLIP_ID Motion presets are relative to the clip's current transform. Look presets add or replace one effect, and ``none`` removes it. Speed and repeat retime every keyframe and change the clip's length; ``clip speed --mode reset`` restores normal speed. Other menu actions are plain edits: rotate and layout with ``clip set``, crop with ``effects add Crop``. The commands also work in ``edit apply`` and ``edit bulk``. .. _cli_text_ref: Adding and styling text ~~~~~~~~~~~~~~~~~~~~~~~ ``text add`` creates a text and places it as a clip, using the same text as the editor's **Text** tool. Options you leave out use the editor's default style: .. code-block:: bash openshot-cli text add --text "Opening Night" --layer 5000000 --position 2 --duration 4 \ --place lower-third --font "Noto Sans" --size 72 --bold --color "#ffffff" \ --background "#80000000" --background-padding 16 --background-corner 12 openshot-cli text get CLIP_ID openshot-cli text set CLIP_ID --stroke black --stroke-width 3 openshot-cli text set CLIP_ID --text $'Two\nlines' --line-spacing 1.4 openshot-cli text fonts --search noto openshot-cli text list --search opening The words, font, size, alignment, box width and default colors belong to the text in Project Files and are shared by every clip that uses it, just like in the editor. ``text set`` on one clip changes all of them and lists them in ``changed_clip_ids``; ``--this-clip-only`` gives that clip its own copy first. ``clip add FILE_ID`` places another clip of a text from ``text list``. Sizes are in pixels at the project resolution, and colors are ``#RRGGBB``, ``#AARRGGBB`` (with alpha), a CSS name, or ``transparent``. ``--place`` puts the box at the center, an edge or corner, or a lower third. ``--line-spacing`` is a multiple of the normal distance between lines (1 is normal), and ``--background-corner`` rounds the background and border corners by that many pixels. A text clip is an ordinary clip. Position, scale, rotation, opacity, timing, fades, motion presets and effects all use the normal ``clip`` commands. Font size, padding, box width, and letter and line spacing set the size of the text box, so they cannot be keyframed; to animate the size of text, keyframe the clip's scale. Each clip can animate its own text colors and outline and border widths with the same keyframe commands as any other property: .. code-block:: bash openshot-cli clip keyframe list CLIP_ID openshot-cli clip keyframe set CLIP_ID --property text_color.alpha --space clip --unit seconds --at 0 --value 0 openshot-cli clip keyframe set CLIP_ID --property text_color.alpha --space clip --unit seconds --at 1 --value 255 The animated properties are ``text_color``, ``text_background``, ``text_stroke`` and ``text_border`` (colors, with ``.red``, ``.green``, ``.blue`` and ``.alpha`` from 0 to 255), plus ``text_stroke_width``, ``text_border_width`` and ``text_background_corner``. A clip's own animation wins over the shared style, and ``text get`` lists which styles a clip animates. ``text reset CLIP_ID`` returns a clip to the default style, like **Text → Reset Style**; ``--keyframes-only`` just removes the clip's own animation. To style many texts at once, select them with ``{"text":true}``: .. code-block:: bash openshot-cli edit bulk --select '{"text":true}' --json '[{"method":"text.set","params":{"font_family":"Noto Sans","stroke_width":2}}]' Applying a batch of edits ~~~~~~~~~~~~~~~~~~~~~~~~~ ``edit apply --json @edits.json --expect-revision 12`` accepts up to 256 ordered mutation commands, using dotted command names such as ``clip.set`` and ``effects.add`` (the older ``effect.add`` spelling also works):: [ {"method":"project.profile.set","params":{"id":"builtin:01280x0720p0024_16-09"}}, {"method":"file.import","as":"media","params":{"path":"/tmp/video.mp4"}}, {"method":"clip.add","as":"shot","params":{"file_id":{"$ref":"media.id"},"layer":1000000,"start":10,"end":15}}, {"method":"clip.fade","params":{"id":{"$ref":"shot.id"},"fade_in":0.5,"fade_out":0.5}} ] The optional ``as`` binds a result for later commands in the same batch. A ``{"$ref":"shot.id"}`` object substitutes that result's field. References only resolve earlier names; misspellings, forward references, and duplicate names fail before live updates. The response includes ordered compact results and a ``refs`` map of actual IDs. All changes in a successful batch form one undo/redo step. ``project.profile.set`` also supports populated timelines. Opening, saving, exporting, and inspection commands stay outside edit batches. Each command's help lists its JSON parameter names, including the underscore spelling of shell flags (for example, ``--fps-num`` becomes ``fps_num``). Validating batches and handling errors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All commands in edit batches preflight against a detached project before any live updates. Invalid input leaves the live project and revision unchanged. Valid batches form one undo group. Unexpected runtime failures can still produce partial changes; errors report completed operations. A timeout does not imply cancellation, so inspect state before retrying mutations. Precise keyframe editing ~~~~~~~~~~~~~~~~~~~~~~~~ ``clip``, ``transition``, and ``effects`` support ``keyframe list``, ``set``, ``remove``, ``clear``, ``transform``, ``copy``, and ``paste``. Property paths can address nested curves, such as ``color.red`` on a Chroma Key effect. Editing a nested curve preserves sibling channels. Run ``keyframe list ID`` without a property to discover curve paths and point counts. Discovery and point listings include trim/position timing context; point listings also report native frame coordinates. ``get`` and ``properties`` expose the complete native object and property metadata. Errors identify invalid fields, suggest close property names, and explain coordinate corrections. Choose coordinates explicitly with ``--space native|clip|timeline`` and ``--unit frames|seconds``. All frames use project FPS and are 1-based; seconds start at zero and snap to the nearest frame. Native is the existing engine keyframe coordinate (including source trim). Clip coordinates start at the visible clip in-point; timeline coordinates start at project time zero. Attached effects use their parent clip's timing. These coordinates address animation time, not the media frames selected by a time-remapping curve. For a clip positioned at 5 seconds, trimmed at 2 seconds, in a 30 fps project, clip frame 1, timeline frame 151, and native frame 61 address the same point. Position and trim snap independently to the project frame grid. Listing an entire curve can include hidden points with nonpositive clip/timeline coordinates. Legacy ``--frame`` still means a native frame and cannot combine with ``--at``. Examples:: openshot-cli clip keyframe set CLIP --property location_x --space clip --unit seconds --at 0 --value -1 openshot-cli clip keyframe set CLIP --property location_x --space clip --unit seconds --at 1 --value 0 --interpolation bezier --handles '{"handle_left":{"X":0.2,"Y":0.9}}' openshot-cli effects keyframe set EFFECT --property color.red --space clip --at 31 --value 200 openshot-cli clip keyframe list CLIP --property location_x --space clip --unit seconds openshot-cli clip keyframe transform CLIP --property location_x --space clip --start 1 --end 31 --scale 2 --offset 15 openshot-cli clip keyframe copy TARGET --property location_x --source-id SOURCE --space clip --start 1 --end 31 --at 1 --mode merge openshot-cli clip keyframe remove CLIP --property location_x --space clip --at 31 openshot-cli clip keyframe clear CLIP --property location_x --value 0 Interpolation, easing, and preview ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Interpolation describes the segment **into the destination point**. Linear gives a steady rate between points. Constant holds the preceding value until the destination, then jumps. Native default Bezier handles ease at both ends of each segment. Adding an intermediate point can therefore introduce an unintended slowdown; for one eased move, start with two endpoints. Normally leave handles alone and choose a named preset for a specific style. Discover the same easing presets used by the editor's menus, without a session:: openshot-cli clip keyframe presets Apply a preset to the incoming segment by setting its destination:: openshot-cli clip keyframe set CLIP --property scale_x --space clip --unit seconds --at 0 --value 1 openshot-cli clip keyframe set CLIP --property scale_x --space clip --unit seconds --at 4 --value 1.2 --easing ease-in-out The easing option implies Bezier. It sets the previous point's outgoing handle and the destination's incoming handle together, preserving other handles and point values. An earlier point must exist. Do not combine it with custom handles or a different interpolation. Presets work in batches and bulk templates. The GUI preset **ease** ("Ease (Default)") differs from the native handles used by plain Bezier interpolation. Back presets can overshoot endpoint values. Inspect motion **before rendering**, using the native curve evaluator:: openshot-cli clip keyframe preview CLIP --property scale_x --space clip --unit seconds --start 0 --end 4 openshot-cli clip keyframe preview CLIP --property scale_x --space clip --unit seconds --at 2 Preview is read-only and works identically for effects and transitions. It returns values and signed incoming_rate / outgoing_rate in property units per second, calculated from immediately adjacent frames. These are finite differences, not analytic derivatives. At native frame 1 the incoming rate is null. Adjacent-frame rates can inspect outside the requested range. Near-zero rates around an interior point reveal a pause; differing rates reveal a speed change. Constant interpolation reveals a jump at the destination. Without a range, preview spans the curve's first and last points. Ranges are inclusive, with 17 evenly spaced samples by default (--count: 2–256). Keyframes and their immediate neighbors inside the range are also included, so a sparse sample count will not hide a keyframe stall. The maximum is 1024 samples; larger requests require a narrower range. --at samples one frame. Preview reports requested-space coordinates and actual native frames; seconds snap to project frames as they do for editing. For advanced custom handles, both X and Y are normalized to the segment: X is a fraction of its frame span; Y is a fraction of its value change. The first control comes from the previous point's handle_right, the second from the destination's handle_left. Native defaults are right=(0.5, 0), left=(0.5, 1), with flat endpoint tangents. Changing handle_type alone does not recalculate a continuous tangent through surrounding points. Existing handles are preserved when moving a point. Keyframe ranges are **inclusive**, unlike clip-selection time ranges. List emits ``points`` whose ``co.X`` values use the requested coordinate space/unit. Pass that array to ``keyframe paste --json @points.json`` with the same space/unit, choosing ``--mode merge`` (replace matching frames, retain others) or ``--mode replace`` (replace the entire curve). ``copy`` accepts a source of the same object kind, an optional ``--source-property``, and anchors the first selected source point at ``--at`` on the target. Other curves and source objects remain unchanged. ``transform`` applies a positive time scale around the first selected point, or ``--pivot``, followed by a signed ``--offset`` in the chosen unit. Frame snapping that creates duplicate coordinates is rejected, including collisions with points outside the selected range. Native coordinates must remain at least 1. Native normalized Bézier handles and interpolation travel with each point; handles are not absolute frame coordinates. ``set --handles`` changes only supplied handles. Interpolation belongs to the destination point. ``clear`` retains a constant base point at native frame 1: specify ``--value`` or sample the existing curve with ``--at`` (default native frame 1). Removing the last point also retains a constant base, so subsequent keyframe additions remain valid. Selecting and editing many clips ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use ``edit apply --dry-run`` to validate a batch without changing the project. Use ``edit bulk`` to repeat a small command template for each selected clip, with all changes grouped into one undo step. First preview a selection:: openshot-cli edit select --json '{"layer":1000000,"start":5,"end":20,"effect":"Saturation"}' Selectors support ``ids`` (unique clip ID array), ``layer``, ``start``/``end`` (timeline seconds), ``file_id``, ``effect`` (class name or alias), and ``text`` (``true`` selects text clips). Filters combine with AND. Time ranges select clips overlapping ``[start, end)``; they do not trim those clips. Results are ordered by position, layer, then ID, and include IDs, summaries, lock state, and the current revision. Unknown IDs are errors. An empty selector is rejected; use ``{"all":true}`` explicitly for every clip. Selections are bounded to 256 clips and are never silently truncated. For example, save this array as ``templates.json``:: [ {"method":"clip.adjust","params":{"values":{"position":{"add":2},"volume":{"multiply":0.5}}}}, {"method":"effects.add","as":"look","params":{"type":"Saturation"}}, {"method":"effects.keyframe.set","params":{"id":{"$ref":"look.id"},"property":"saturation","space":"clip","at":1,"value":0}}, {"method":"effects.keyframe.set","params":{"id":{"$ref":"look.id"},"property":"saturation","space":"clip","at":31,"value":1.2}} ] Validate it, then apply against the revision returned by selection:: openshot-cli edit bulk --select '{"ids":["CLIP_A","CLIP_B"]}' --json @templates.json --dry-run openshot-cli edit bulk --select '{"ids":["CLIP_A","CLIP_B"]}' --json @templates.json --expect-revision 42 Existing-clip commands inherit ``id``; ``effects.add`` inherits ``clip_id``. Omit these target parameters in templates. Effect edits must reference an earlier named result. Names are local to each selected clip, so ``look.id`` refers to a different effect for each clip. To change existing effect instances by explicit ID, continue using ``edit apply``. The selected ID set is fixed before expansion; changes to position or effects do not change the remaining targets. ``clip set`` applies absolute properties; ``clip adjust`` applies ``multiply`` then ``add`` to a numeric property or every value in a curve, preserving point timing, interpolation, and normalized handles. It validates resulting values, including nonnegative positions and volume. Structural fields remain protected. Bulk operations reject empty selections, locked target tracks, and more than 256 expanded commands. Every expanded operation passes detached preflight before any live edit. Dry runs do not reserve generated IDs. Use ``--expect-revision`` to reject stale selections. Successful batches are one undo step, including after save/reopen. GUI refreshes are batched. Unexpected runtime/listener errors can still leave a partial transaction; the error reports completed operations and undo reverts that group, as with ``edit apply``. Profiles -------- Discover profiles and match imported video without guessing IDs:: openshot-cli profile list --search 720 openshot-cli profile get builtin:01280x0720p0024_16-09 openshot-cli profile match --file FILE_ID openshot-cli project profile get openshot-cli project profile set --from-file FILE_ID openshot-cli project profile set builtin:01280x0720p0024_16-09 openshot-cli project profile set --json '{"width":640,"height":352,"display_ratio":{"num":20,"den":11},"fps":{"num":24000,"den":1001}}' Catalog entries include stable IDs, descriptions, dimensions, rational FPS, aspect ratios, and scan settings. List/search is paginated. Source matching returns exact IDs and ranked alternatives with explicit differences. Setting from a file requires an exact match unless ``--create-custom`` is specified; it never silently chooses a nearby profile. Still images and audio-only sources cannot define a video profile. Matching uses declared source FPS. Custom settings are embedded in the saved project, including rational rates, so reopening does not require installing a separate profile file. Project profile changes use existing frame-rate conversion and one undo transaction. Undo/redo restores clip timing and keyframes, including rounding-sensitive positions. Export can independently select a profile without changing the project. Saved undo history follows the editor's history-limit preference. The limit is a soft action budget: all records belonging to retained transactions are kept, so saving cannot truncate a large batch into a partial undo action. Zero disables saved history. The separate 256-command batch request bound still applies. Inspecting media and timelines ------------------------------ Inspect clip timing and track layout as text or JSON, or render images to review composition and framing before exporting. Timeline summaries ~~~~~~~~~~~~~~~~~~ Use a text view for a quick overview, or structured JSON for scripts and agents:: openshot-cli timeline view --start 5 --end 12 openshot-cli timeline view --start 5 --end 12 --format json openshot-cli timeline overview --start 5 --end 12 ``timeline view`` defaults to compact text with used tracks, object IDs, timeline/source intervals, stream state, gain, and gaps/overlaps. Use ``--detail summary|clips|full`` to choose detail, ``--format json`` for structured context, and ``--start/--end``, ``--layer``, and pagination to focus the result. ``timeline overview`` supplies compact structured context without image bytes: ordered IDs, sequence per track, timeline/source intervals, visible trim ranges, frame coordinates, audio/video state, effects, and neighboring gaps or overlaps. Intervals and frame spans are end-exclusive; frame numbers are one-based. Source frames use source FPS; timeline and keyframe coordinates use project FPS. Use ``--layer`` and ``--start/--end`` to focus, and ``--limit/--offset`` to paginate (default 100, maximum 500 items). Time-remapped clips explicitly withhold inferred source mappings. Use the returned revision with ``edit apply --expect-revision``. Frame previews and contact sheets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Render a single frame with ``thumbnail`` or sample a range with ``strip``. Use ``file`` to inspect source media and ``timeline`` to inspect the composed video, including effects and layered clips:: openshot-cli file thumbnail FILE_ID --frame 301 --output /tmp/source.png openshot-cli file strip FILE_ID --start 10 --end 20 --count 12 --output /tmp/source-strip.png openshot-cli timeline thumbnail --frame 91 --output /tmp/timeline-frame.png openshot-cli timeline strip --start 0 --end 20 --count 12 --output /tmp/timeline-strip.png Frame images default to 320x180 pixels; contact sheets default to 160x90 per tile, plus timecode labels. Use ``--width`` and ``--height`` to choose output pixels. Responses include exact sample/frame metadata. Contact sheets help review composition across a sequence; use keyframe previews and rendered video to assess motion between those samples. Timeline images ~~~~~~~~~~~~~~~ Capture the editor's track layout, including its ruler, thumbnails, effects, transitions, and waveforms:: openshot-cli timeline view --start 0 --end 20 --pixels-per-second 80 --output /tmp/tracks.png Specifying ``--output`` selects image format; ``--format image`` also selects it explicitly. The capture does not change the editor's viewport or project. Responses include clip IDs and timing alongside pixel bounds. Images default to 1280 pixels wide, with height fitted to used tracks. Use ``--width``, ``--height``, or ``--all-tracks`` to adjust the layout, and ``--track-size`` or ``--track-label-width`` to adjust tracks and labels. The start/end range determines zoom; ``--pixels-per-second`` instead derives the width from the time range. Audio waveform views ~~~~~~~~~~~~~~~~~~~~ Choose ``--mode waveforms`` to inspect audio envelopes on the timeline:: openshot-cli timeline view --start 5 --end 12 --mode waveforms --output /tmp/waves.png ``--mode auto`` uses the existing cached waveform display; ``--mode thumbnails`` shows thumbnails instead. Waveforms represent source peak/RMS levels with clip volume and timing adjustments, before audio effects or mixing. Uncached waveform extraction decodes whole sources, limited to 600 seconds per source and 1200 source-seconds per request. Narrowing the visible range does not reduce that decoding work. For longer sources, generate waveforms in the editor first or use thumbnail mode. Subsequent requests can reuse cached waveforms. Image output and limits ~~~~~~~~~~~~~~~~~~~~~~~ Image paths must be new PNG files in existing directories. Images are limited to 4096 pixels per axis, 8,388,608 total pixels, and 64 contact-sheet samples. Requests beyond these limits fail before rendering. Images are written to files; JSON responses include their paths and ``image_bytes`` sizes. Inspection waits for the image to finish, and large requests can briefly occupy the editor. Handling command timeouts ------------------------- A request timeout does not mean a mutation failed. Use the operation ID in the error with ``operation get ID`` before retrying. ``operation list`` discovers recent mutations and their states, revisions, and outcomes. Completed operations retain their results when small enough, including returned object IDs. Storage is bounded to 100 operations and 4 MiB, with individual result bodies omitted above 256 KiB. These records last only for the running session. They do not restore projects after a crash or prevent a repeated command from applying the same edit again. Export jobs have their own status/list commands.