--progress jsonl — machine-readable progress events
photomap, flightmap, embed, check, doctor, convert, validate,
and verify-sun accept --progress jsonl. In
this mode a command writes one JSON object per line to stdout and nothing
else — human/informational output is suppressed, and warnings and log
messages go to stderr. A non-zero exit code always means the run failed;
for success, read the result event's ok field (see the embed nuance
under the terminal rule below). Lines are pure ASCII (non-ASCII text is
JSON-escaped and round-trips intact through any JSON parser), so the stream
is safe to read under any pipe encoding. This is the interface for frontends
and scripts:
dji-embed flightmap D:\Drone\trip --progress jsonl
{"v":1,"event":"start","command":"flightmap"}
{"v":1,"event":"progress","current":1,"total":3,"item":"DJI_0001"}
{"v":1,"event":"progress","current":2,"total":3,"item":"DJI_0002"}
{"v":1,"event":"progress","current":3,"total":3,"item":"movie"}
{"v":1,"event":"warning","message":"No GPS telemetry","item":"movie"}
{"v":1,"event":"result","ok":true,"outputs":["D:/Drone/trip/flightmap.html"],"summary":{"flights":2,"skipped":1,"joined_files":0}}
Stability
- Every event carries
"v": 1. Additive changes (new fields, new event types) do not bumpv; consumers must ignore fields and event types they do not recognise. Breaking changes bumpv. - The machine-checkable contract lives in
progress_jsonl.schema.json(JSON Schema, draft 2020-12, validates any single event line). The test suite validates every emitted line against it.
Events
| event | fields | meaning |
|---|---|---|
start |
command (required), total (optional) |
First event of every run. total is omitted when the item count is not known up front (render an indeterminate progress bar). |
progress |
current, total (required), item (optional) |
One item finished being picked up for processing. current counts from 1 to total. |
warning |
message (required), item (optional) |
Non-fatal problem; the run continues. |
result |
ok, outputs, summary (all required) |
Terminal event of a run that completed. outputs = absolute paths of files written (may be empty). summary is command-specific (below). |
error |
message (required), item (optional) |
Terminal event of a run that failed; the process exits non-zero. No result follows. |
Terminal rule: a stream starts with start and ends with exactly one of
result or error — including on unexpected internal failures, which
surface as an error event before the non-zero exit. With one documented
nuance: embed processes files independently and keeps its existing
exit-code behaviour, so a run where some files failed still exits 0 and
ends in result with "ok": false (per-file problems are warning events;
the counts are in summary). For embed, therefore, treat result.ok —
not the exit code — as the success signal. For every other command result
implies "ok": true.
Warnings are not live: warning events for skipped items are typically
emitted after the scan completes (once the skipped set is known), not
interleaved with the progress events. Attribute them by their item
field, never by arrival order.
Per-command notes
flightmap
- One
progressevent per.SRTfile scanned;startcarries nototal(the file count is discovered during the scan — taketotalfrom the firstprogressevent). - One
warningper SRT without GPS telemetry (messageis"No GPS telemetry", the file name is initem), emitted after the scan. summary:{"flights": N, "skipped": N, "joined_files": N}—joined_filescounts source files that were chained into multi-segment flights.
photomap
- No
progressevents in v1 (the photo scan is a single batch ExifTool call);starthas nototal. Expectstart→ warnings →result. summary:{"photos": N, "skipped": N}(mapped vs no-GPS).--servecannot be combined with--progress jsonl(serving blocks forever; frontends open the written HTML themselves).
embed
- One
progressevent per video file. summary:{"processed": N, "total": N, "warnings": N, "errors": N, "output_directory": "..."};outputs=[output_directory].okisfalsewhen any file errored (see terminal rule above).
check
- One
progressevent per path argument. outputsis empty.summary:{"checked": N, "files": {"<path>": {<metadata flags>}}}— the per-file object ischeck's existing detection result:{"gps": bool, "altitude": bool, "creation_time": bool}. A path that does not exist or cannot be read yields{}and awarningevent ("Not found or unreadable") — the run still ends inresultwith"ok": true.- A directory argument stands for its top-level media files
(
*.mp4/*.mov/*.jpg/*.jpeg/*.dng, case-insensitive, no recursion):start.total, theprogressevents andsummary.filesall name the expanded files, never the directory itself. A directory with no media files contributes nothing and yields onewarningevent ("No media files found",item= the directory) — the run still ends inresultwith"ok": true. A directory that cannot be listed (e.g. a permissions error) is handled the same way: it contributes nothing and yields onewarningevent ("Not found or unreadable",item= the directory) rather than aborting the run.
doctor
- No
progressevents. Onewarningper missing tool (item= tool name).outputsis empty.summary:{"ok": bool, "tools": {"ffmpeg": {"present": bool}, "exiftool": {"present": bool, "version", "source", "path", "decode"}}, "system": {...}}— the exiftool extras appear only when it is present and its version is readable. - Missing dependencies are a report, not a crash:
"ok": falsewith exit code 0 (same reading rule asembed). - The opt-in online update check never runs under
--progress jsonl; consent for going online stays interactive-only.
convert
- Single-file mode:
startcarriestotal: 1and oneprogressevent fires for the input. Batch mode (-b):starthas nototal(the directory is scanned inside the run); oneprogressevent per candidate file,totalon theprogressevents. - Batch files whose telemetry cannot be read (
Mp4TelemetryError) are skipped with onewarningeach (item= file name); in single-file mode the same failure is fatal (errorevent, non-zero exit). outputs= absolute paths of every file written.summary:{"converted": N, "skipped": N, "format": "gpx"}.
validate
- No
progressevents;starthas nototal. Onewarningper issue found.outputsis empty;summaryis the full validation report (total_files,valid_pairs,issues,warnings,file_analyses). - Findings are a report, not a command failure: a run with issues still
exits 0 and ends in
resultwith"ok": true— readsummary.issues. (Text mode keeps the non-zeroVALIDATION_ERRORexit for scripts.) --format jsoncannot be combined with--progress jsonl(theresultsummary already carries the full report).
verify-sun
- No
progressevents. Onewarningper analysis flag (night,very_low_sun,sun_not_computable— the flag name is themessage). Flags are findings about the footage, not failures:"ok": true. outputsis empty;summaryis the sun summary dict (file,points,sun_computed,utc_start/utc_end, elevation/azimuth stats,flags).--format jsoncannot be combined with--progress jsonl.
Relation to --log-json
--log-json (env DJIEMBED_LOG_JSON) is an older, separate feature: it
formats log lines as JSON for the commands that read it (e.g. doctor)
and is independent of this event stream. The progress-wired commands
do not change their logging format based on it; logs are human-readable
text on stderr for every command, with or without --progress jsonl.
Parse stdout events, treat stderr as free-form diagnostics.