Skip to main content

insta360-rs

Portable Rust tooling for inspecting, calibrating, stitching, and exporting Insta360 INSV media on macOS, Windows, and Linux.

insta360-rs is designed for geometry-stable 360° output, with underwater photogrammetry as its primary use case. It reads the factory calibration and capture metadata stored in each recording, stitches through a deterministic CPU renderer or a portable wgpu compute renderer, and can export equirectangular images or HEVC MP4 video through FFmpeg.

Project status: experimental 0.1. Packet-preserving stream and metadata extraction is camera-independent and accepts one- or two-file input sets. Decoded stitching, image export, and stitched MP4 export are currently implemented only for X5 single-file, dual-track recordings. The parser recognizes ONE X through X6 metadata and calibration records. The API may change before 1.0.

The project is independent and is not affiliated with or endorsed by Insta360. It does not link or execute vendor runtime libraries. Licensed Insta360 and Studio data resources are embedded in an integrity-checked bundle; possessing those assets does not imply that their algorithms are implemented or qualified.

What it does

  • Probes large INSV files without scanning their complete video payload.
  • Opens file-backed stream objects for encoded packet access and seekable frame decoding without intermediate files.
  • Extracts every demuxed stream, packet timing/index, codec extradata, side data, container metadata, and proprietary ExtraInfo record without decoding, stitching, or transcoding. Compatible streams also receive best-effort standalone codec-copy remuxes.
  • Parses ISO-BMFF tracks and the indexed Insta360 trailer.
  • Retains camera name, firmware, serial, layout, codec, crop, rotation, timing, gyro/exposure record descriptors, accessory state, optical profiles, and current/original factory offsets.
  • Parses V1, V2, V3, and V6 offset layouts; V2/V3/V6 have portable projection implementations, while V1 remains inspection-only.
  • Uses per-recording intrinsics, distortion, principal points, extrinsics, and embedded optical-profile curves instead of substituting generic calibration.
  • Resolves X5 Dive Case Pro underwater metadata to the correct refractive profile when the required physical curves are present.
  • Produces fixed-geometry 2:1 equirectangular panoramas with deterministic masks, seams, and low-frequency overlap color matching.
  • Converts identified X5 I-Log footage to Rec.709 through the bundled Studio 3D LUT on both CPU and GPU, or leaves stitched I-Log values LUT-untransformed for downstream grading.
  • Exports selected PNG/JPEG frames through the Rust API and PNG frames through the CLI.
  • Exports finalized 8-bit YUV420 HEVC MP4 video through available FFmpeg encoders.
  • Runs calibrated stitching on CPU everywhere or through native wgpu Metal/D3D12/Vulkan compute backends.
  • Provides progress events, cancellation, bounded pipeline queues, whole-job GPU-to-CPU fallback, and atomic output publication.
  • Offers PyO3 bindings for Python 3.10+.

Packet-preserving extraction does not spatially split a packed dual-fisheye frame. The crate does not currently copy audio into stitched MP4 output, use hardware decoding, run AI seam inference or ColorPlus, apply general crop-aware optical projection, or preserve 10-bit depth in stitched output. Supported X5 recordings have gravity-referenced stabilization and sensor readout correction on both CPU and GPU; see stabilization.

Camera support

Legend:

  • ✅ — implemented in the current public API for the stated scope.
  • ❌ — unavailable in the current implementation.

The distinction matters: recognizing a camera, lens ID, or offset layout is not the same as being able to decode and export that camera's recording. Firmware and recording mode can also change the physical layout and codec.

Housing columns report camera-scoped calibration-profile recognition, not high-level file export. High-level image and video export remains X5-only.

Camera Typical layout Metadata probe Encoded camera-stream extraction⁷ Container / ExtraInfo metadata extraction⁷ Offset/distortion parsing Calibrated high-level render Stitch / image / MP4 export Overlap color matching¹ I-Log → Rec.709¹ ColorPlus / AI color¹ CPU file export wgpu file export Direction Lock / FlowState² Rolling shutter⁸ 10-bit stitched output Waterproof profile Classic dive air profile Classic dive underwater profile X3 Invisible Dive Case air profile X3 Invisible Dive Case underwater profile X5 Dive Case Pro air profile X5 Dive Case Pro underwater profile
ONE X Split pair ≥5.7K; one packed file below³ ✅⁷ ✅⁷ ✅⁴ ✅⁵ ✅⁵ ✅⁵
ONE X2 Split pair ≥5.7K; one packed file below³ ✅⁷ ✅⁷ ✅⁴ ✅⁵ ✅⁵
X3 Split pair ≥5.7K; one packed file below³ ✅⁷ ✅⁷ ✅⁴ ✅⁵ ✅⁵ ✅⁵ ✅⁵
X4 Single-file dual-track ✅⁷ ✅⁷ ✅⁴
X5 Single-file dual-track ✅⁷ ✅⁷ ✅⁴ ✅² ✅⁸ ✅⁶ ✅⁶
X6 Single-file dual-track ✅⁷ ✅⁷ ✅⁴
  1. X5 file export performs fixed-seam, low-frequency overlap radiometric matching. ColorConversion::Auto applies the bundled X5 I-Log-to-Rec.709 CUBE when nested recorded-color metadata identifies I-Log, with the legacy exact I_Log gamma string as a fallback. Preserve disables conversion; ILogToRec709 requests it explicitly and rejects conflicting Standard/Dolby metadata. This is not factory sensor profiling, ColorPlus, or AI color.

  2. X5 Direction Lock fixes the initial heading and levels the horizon. FlowState- style leveling preserves camera heading. Both use compact raw IMU samples, recorded ranges, reliable initial gravity, and validated video timing, including tag-64 value 2 exposure mapping. This is our six-axis filter; absolute compass heading and vendor FlowState equivalence are not claimed.

  3. ONE X through X3 use a _00_/_10_ pair at 5.7K and above, and one packed file below 5.7K. Probe the actual inputs rather than selecting layout from camera name alone. Pairs are accepted by parser/probe, not by the current high-level exporter.

  4. V1/V2/V3/V6 records can be inspected. V2/V3/V6 projection data is renderable by the low-level stitcher; V1 is rejected by stitch preflight. Only X5 V6 has real-recording stitch qualification.

  5. The registry recognizes an offset already encoded for this housing. X1-X3 housing conversion and high-level file export are not implemented.

  6. X5 accepts already-converted lens types 117/118. It can also convert a V6 bare calibration when both source and target six-coefficient physical curves are present. StrictAuto uses only conclusive recorded accessory metadata. CLI/API select these Pro profiles as invisible-dive-case-air and invisible-dive-case-underwater; no separate x5-dive-case-pro-* option exists.

  7. Extraction requires media and a suitable FFmpeg demuxer/muxer build, but no supported camera profile, calibration, stabilization, encoder, or GPU. It preserves every demuxed packet payload with boundaries/timestamps, codec extradata, side data, stream/container metadata, non-mdat boxes, and raw ExtraInfo bytes without decoding or re-encoding. V2/V3 metadata is also emitted as JSON/calibration artifacts when understood; unknown data remains raw with warnings. Compatible video/audio streams receive a best-effort codec-copy MP4/MKV/M4A/MKA. Packed modes remain packed. The generic path has synthetic packet-equality and V2/V3 coverage, not a six-camera release corpus.

  8. Automatic readout correction requires an established source-sensor profile, duration, exposure timing, and complete gyro coverage. Required makes unavailable correction an error; Auto reports an omission. This does not establish arbitrary rotated/cropped recording support. See the exact profile constraints.

Additional registered optical profiles include X2 adhesive spherical and clip-on guards; X3 A/S/AS protectors; X4 A/S/AS protectors; X5 A protector; and X5 bare-underwater lens type 114 when already encoded. ND16/32/64/128 states are parsed, but portable X5 conversion to those filters is not implemented.

Input codec support for decoded stitching depends on recording mode and the linked FFmpeg build. Packet-preserving extraction does not decode or re-encode streams and is not restricted to X5; playable convenience remuxes remain codec/muxer-dependent. The only real stitched-export corpus exercised so far is X5 dual-track 8-bit HEVC. Probe reports indexed gyro/exposure descriptors and counts; use InsvReader::read_record_payload with decode_motion_record or decode_exposure_record to obtain samples.

Installation

Rust library from crates.io

Once published, add the parser and low-level CPU primitives with:

cargo add insta360-rs

For packet-preserving extraction and CPU file workflows:

cargo add insta360-rs --features media

Add portable GPU stitching with:

cargo add insta360-rs --features media,gpu

The package name uses a hyphen; Rust code imports it as insta360_rs. The minimum supported Rust version is 1.88.

Command-line application

CPU-capable CLI:

cargo install insta360-rs --features cli --locked

CLI with the native wgpu backend for the current platform:

cargo install insta360-rs --features cli,gpu --locked

The media and cli features require FFmpeg headers and linkable avcodec, avformat, avutil, and swscale libraries at build time. If FFmpeg is dynamically linked, its shared libraries must also be discoverable at runtime. HEVC video export requires at least one usable HEVC encoder in that FFmpeg build, either software such as libx265 or a supported platform encoder. Extraction requires demuxer/muxer support, but no decoder, encoder, GPU, camera profile, or calibration.

After installation, inspect the actual host rather than assuming acceleration is available:

insta360-rs capabilities
insta360-rs capabilities --json

From source

From the standalone insta360-rs checkout, first make FFmpeg development and link libraries discoverable by ffmpeg-next, then install the CLI:

cargo install --path . --features cli,gpu --locked

For an in-tree build and capability smoke test:

cargo run --features cli,gpu -- capabilities

Run the test suite with all optional paths enabled:

cargo test --all-features

Cargo features

Feature Default Purpose Extra runtime requirement
none Bounded INSV parser, metadata, profiles, calibration, telemetry, motion, and deterministic CPU stitch primitives None
media Direct stream readers, packet/metadata extraction and codec-copy remux, decoded frame export, HEVC MP4 export, progress, and cancellation Linkable FFmpeg; deploy shared libraries when dynamically linked
gpu Safe wgpu compute stitcher and adapter discovery Compatible native GPU adapter and driver
cli Builds the insta360-rs executable; implies media FFmpeg

gpu does not imply media: applications can use the low-level GPU stitcher with their own decoded frames. Enable both for GPU file conversion.

Direct stream access and extraction

insta360-rs extract recording.insv extracted

Use extract(&InputSet, output_dir) from Rust or insta360_rs.extract(input, output_dir) from Python. To read packets or seek and decode unstitched frames directly from the original file, use MediaSource and MediaStream; no intermediate MP4 is created. See stream access and extraction for API examples, the output layout, preservation guarantees, and storage requirements.

Rust quick start

Probe without decoding video

The default feature set is sufficient:

use insta360_rs::{probe, InputSet};

fn main() -> insta360_rs::Result<()> {
    let inputs = InputSet::discover("recording.insv")?;
    let info = probe(&inputs)?;

    println!("camera: {:?}", info.camera);
    println!("video tracks: {}", info.video_tracks.len());
    println!("offset versions: {:?}", info.offset_versions);
    println!("optical profiles: {:?}", info.optical_profiles);
    Ok(())
}

InputSet::discover finds the matching _00_ or _10_ file for legacy paired recordings when it exists. The CLI extract command performs this discovery for one input; probe requires both paths explicitly.

Extract encoded streams and metadata

This requires features = ["media"] and works independently of decoded stitching support:

use insta360_rs::{extract, InputSet};

fn main() -> insta360_rs::Result<()> {
    let inputs = InputSet::discover("recording.insv")?;
    let report = extract(&inputs, "recording-extracted")?;

    println!(
        "{} streams, {} ExtraInfo records",
        report.stream_count, report.record_count
    );
    println!("manifest: {}", report.manifest_path.display());
    for warning in report.warnings {
        eprintln!("warning: {warning}");
    }
    Ok(())
}

The destination must be absent or an empty, non-symlink directory. Work is staged beside it and published only after every input succeeds. The report contains absolute output, manifest, and artifact paths plus counts and warnings.

Export an X5 video

This example requires features = ["media", "gpu"] and explicitly disables stabilization. Use Stabilization::DirectionLock for gravity-referenced output with a fixed initial heading; exposure-file PTS mapping is supported.

use std::time::Duration;

use insta360_rs::{
    AudioPolicy, ColorConversion, EquirectangularProjection, Exporter,
    InputSet, MediaAcceleration, OpticalSetup, ProcessingBackend,
    Stabilization, StitchConfig, VideoExportOptions,
};

fn main() -> insta360_rs::Result<()> {
    let inputs = InputSet::discover("recording.insv")?;
    let config = StitchConfig {
        optical_setup: OpticalSetup::StrictAuto,
        stabilization: Stabilization::Off,
        backend: ProcessingBackend::Auto,
        color_conversion: ColorConversion::Auto,
        ..StitchConfig::default()
    };
    let exporter = Exporter::new(inputs, config)?;

    let result = exporter
        .export_video(
            "stitched.mp4",
            VideoExportOptions {
                quality: 90,
                audio: AudioPolicy::Drop,
                acceleration: MediaAcceleration::Auto,
                projection: Some(EquirectangularProjection {
                    width: 5760,
                    height: 2880,
                }),
                start: Some(Duration::from_secs(120)),
                duration: Some(Duration::from_secs(60)),
            },
        )
        .wait()?;

    println!("wrote {:?} with {:?}", result.outputs, result.backend.selected);
    Ok(())
}

ExportJob also exposes bounded progress-event polling and cancellation. A successful wait() is the publication contract.

CLI usage

insta360-rs extract <INPUT> [<SECOND_INPUT>] <OUTPUT_DIR> [--json]
insta360-rs probe <INPUT>... [--json]
insta360-rs export-frames <INPUT> <OUTPUT_DIR> \
  (--indices <N,...> | --timestamps <SECONDS,...>) [OPTIONS]
insta360-rs export-video <INPUT> <OUTPUT.mp4> [OPTIONS]
insta360-rs capabilities [--json]

Run insta360-rs <COMMAND> --help for the generated reference.

Extract encoded streams and metadata

With one input, the matching legacy sibling is discovered automatically:

insta360-rs extract recording.insv recording-extracted

Or supply a split pair explicitly and return the completed report as JSON:

insta360-rs extract \
  VID_20240101_120000_00_001.insv \
  VID_20240101_120000_10_001.insv \
  recording-extracted \
  --json

extract accepts exactly one or two inputs and no stitch, color, quality, or GPU options. With two inputs it validates and orders _00_ before _10_. The destination must be absent or an empty, non-symlink directory; sibling staging is atomically published only after every input succeeds.

Each source is written below input-00, input-01, and so on. Every stream directory contains packets.bin, packets.jsonl, extradata.bin, side_data.bin, and metadata.json; a compatible codec-copy operation also adds media.mp4, .mkv, .m4a, or .mka. Container artifacts retain non-mdat boxes, mdat headers, the raw ExtraInfo tail and records, decoded known metadata JSON, and calibration/profile payloads. The root manifest.json describes every artifact and preservation limit. This is component extraction, not a byte-for-byte backup of unused mdat space, and raw plus playable copies can require roughly twice the encoded media size.

Without --json, stdout reports input/stream/record counts and output paths; warnings use stderr. With --json, stdout is an ExtractionReport containing output_dir, manifest_path, input_count, stream_count, record_count, files, and warnings.

Inspect an INSV

insta360-rs probe recording.insv
insta360-rs probe recording.insv --json

For a legacy split recording, pass the pair in primary/secondary order:

insta360-rs probe VID_20240101_120000_00_001.insv \
  VID_20240101_120000_10_001.insv --json

Probe reads the ISO-BMFF headers, movie metadata, trailer index, and bounded metadata record. It does not decode every frame or scan the entire media payload.

Export stitched frames

By timestamps:

insta360-rs export-frames recording.insv frames \
  --timestamps 1.0,2.5,4.0 \
  --width 5760 \
  --optical-setup strict-auto \
  --stabilization off \
  --backend auto

By zero-based decoded frame indices:

insta360-rs export-frames recording.insv frames \
  --indices 0,30,60 \
  --stabilization off \
  --backend cpu

Exactly one of --indices or --timestamps is required. CLI frame export writes frame_<selection>.png. The Rust and Python APIs additionally expose JPEG output. --width must be a non-zero even panorama width; height is always width / 2. Without it, the default panorama is twice the fisheye track width.

Convert an INSV to stitched MP4

insta360-rs export-video recording.insv stitched.mp4 \
  --start 120 \
  --duration 60 \
  --width 5760 \
  --quality 90 \
  --audio drop \
  --optical-setup strict-auto \
  --stabilization off \
  --color-conversion auto \
  --backend auto \
  --media-acceleration auto

The current command accepts one X5 INSV containing exactly two synchronized video tracks. It writes an HEVC MP4 with 8-bit YUV420 video. Existing output files are never overwritten.

--start and --duration are source-relative seconds. The interval is half-open, [start, start + duration), and the first output frame is rebased to timestamp zero. Omit --duration to continue to the end.

During export, <output>.insta360-rs-part is deliberately incomplete and will usually not open in VLC even if renamed to .mp4: FFmpeg has not written the MP4 trailer. On success the encoder is flushed, the trailer is written, and the temporary file is atomically renamed. Failure or cancellation removes it.

CLI options

Shared stitch options:

Option Values Default Meaning
--optical-setup strict-auto, bare-air, bare-underwater, waterproof-case, dive-case-air, dive-case-underwater, invisible-dive-case-air, invisible-dive-case-underwater, clip-on-lens-guard, adhesive-sphere-lens-guard, protector-a, protector-s, protector-as, nd16, nd32, nd64, nd128 strict-auto Requests an exact setup. It succeeds only when the recorded lens type matches or an evidence-backed conversion exists; strict-auto uses conclusive recorded metadata.
--stabilization off, flow-state, direction-lock direction-lock Gravity-referenced correction with validated exposure/video timing.
--rolling-shutter auto, off, required auto Source-sensor motion correction; requires an enabled stabilization mode.
--backend auto, cpu, gpu auto Stitch renderer. auto attempts GPU and may restart the whole job on CPU. Explicit choices are strict.
--color-conversion auto, preserve, i-log-to-rec709 auto Converts positively identified X5 I-Log with the bundled Rec.709 LUT, leaves stitched values LUT-untransformed, or explicitly requests X5 I-Log conversion.

Frame-selection options:

Option Values Default Meaning
--indices comma-separated integers none Zero-based synchronized decoded-frame indices. Conflicts with --timestamps.
--timestamps comma-separated non-negative seconds none Selects the first synchronized frame at or after each source-relative target. Conflicts with --indices.

Output-size option for frames and video:

Option Values Default Meaning
--width non-zero even integer source-derived Equirectangular width; height is half.

Video-only options:

Option Values Default Meaning
--quality 1..=100 90 HEVC quality target.
--start non-negative seconds 0 Source-relative start.
--duration positive seconds to end Requested interval length; zero is rejected.
--audio drop, copy drop Only drop is implemented; copy returns a capability error.
--media-acceleration auto, software, hardware auto HEVC encoder selection, independent of the stitch backend.

--media-acceleration hardware requires an eligible hardware HEVC encoder; software requires a software encoder. auto tries eligible encoders in priority order. Decode is currently software in every mode, and an encoder failure after frames have already been submitted does not restart the job.

Direction Lock

Direction Lock preflight validates the gyro data and timestamp mapping:

insta360-rs export-video recording.insv locked.mp4 \
  --audio drop \
  --stabilization direction-lock

Both modes use the full recording's IMU pre-roll and actual presentation samples, so selected timestamps and video trims retain the same heading anchor. --rolling-shutter auto is the default; use required to demand sensor readout correction or off to apply only global stabilization. --stabilization off bypasses motion entirely and conflicts with --rolling-shutter required. Missing timing, unknown sensor profiles, unreliable initial gravity, saturation, and telemetry gaps fail preflight. Auto reports unavailable readout correction.

See stabilization conventions and limits for metadata requirements and the distinction between horizon leveling and absolute heading.

GPU processing

The GPU path is compute-only and uses safe wgpu; no vendor runtime or graphics API type crosses the public API boundary.

INSV → FFmpeg software decode
     → direct 8-bit YUV420 upload, or CPU swscale to RGB
     → wgpu projection + distortion + masks + radiometry + fixed seam blend
     → optional bundled X5 I-Log 3D LUT
     → GPU RGB still, or BT.709 limited-range YUV420 video
     → synchronous CPU-visible readback
     → Rust PNG/JPEG encoder, or FFmpeg HEVC encoder

The adapter, device, pipelines, bind groups, and dimension-dependent buffers are retained and reused for a job. Projection, bilinear sampling, optical validity masks, overlap statistics, color gains, fixed high-frequency seam, two-band blend, optional 3D LUT, and video RGB-to-YUV420 conversion run on the GPU.

Current transfer boundaries are important: decoding remains on the CPU, each frame is synchronously read back, and FFmpeg receives CPU-visible output. There are no hardware decode surfaces, native decoder-to-wgpu sharing, zero-copy encoder surfaces, or asynchronous frame slots yet.

--backend auto attempts one complete GPU export. Only a typed GPU initialization or processing failure triggers cleanup and a complete restart on CPU; it never mixes CPU and GPU frames in one result. --backend gpu and --backend cpu never fall back.

GPU platform support

This crate uses wgpu's native backend names but deliberately enables only one backend per supported desktop OS. Upstream wgpu may support additional targets or APIs that are not compiled here.

Target wgpu backend compiled by insta360-rs GPU stitching Real X5 media exercised CPU fallback
macOS Metal ✅ One Apple/Metal host
Windows Direct3D 12 ❌ Pending
Linux Vulkan ❌ Pending

OpenGL/GLES is not enabled. A compiled backend still requires a compatible adapter and driver; check insta360-rs capabilities on the target machine.

GPU stitching and hardware encoding are independent. Depending on the FFmpeg build and host, encoder discovery may find VideoToolbox, Media Foundation, NVENC, AMF, VAAPI, libx265, or libkvazaar. capabilities reports the exact encoders visible at runtime.

Current performance reference

Single-run X5 measurements on one Apple Metal host are included only as an implementation reference, not a cross-platform promise:

Output CPU + libx265 wgpu + libx265 wgpu + VideoToolbox
1920×960 10.38 fps 13.79 fps (1.33×) 40.33 fps (3.89×)
5760×2880 1.28 fps 2.54 fps (1.99×) 27.58 fps (21.57×)

These are matched 15-second runs, but not three-run medians. See performance details for quality metrics, bitrate, and measurement limitations.

Calibration and underwater capture

Factory calibration belongs to the recording. Resolution follows this order:

  1. explicit caller optical setup;
  2. conclusive recorded accessory/offset state and automatic guard result;
  3. lens type already encoded in the current offset;
  4. an explicit ambiguity or unsupported-conversion error.

Registry values supply camera-family FOV, blend angle, lens identity, and mask recipes that are not per-device measurements. They never replace the recording's intrinsics, distortion coefficients, principal points, or extrinsics. A valid recorded blend angle takes precedence unless the optical setup was converted, in which case the target profile's fallback remains in control.

For the supplied X5 Dive Case Pro underwater recording, strict-auto reads offset state 10 and converts the type-113 V6 factory calibration to the type-117 InvisibleDiveWater profile. Do not select an underwater profile only because a scene visually contains water: the setting describes the camera, housing, and medium that created the refractive geometry.

For photogrammetry, keep output dimensions, optical setup, stabilization, seam, and color pipeline identical across the dataset. The default fixed seam avoids dynamic optical-flow changes in high-frequency feature ownership.

See calibration and settings for the offset layouts, profile conversion, masks, and recommended capture policy.

Bundled licensed Insta360 and Studio assets

The library ships 41 original Insta360 and Studio data resources through the insta360-rs-data-core and insta360-rs-data-enhancement dependencies (about 20.8 MiB uncompressed). The files live under data/*/assets/ in this repository; each published crate stays below 10 MB. They are compiled into the library with include_bytes! and available directly at runtime.

The bundle currently contains:

  • camera configuration JSON for ONE X (One2), ONE X2, OneR/OneRS, X3, X4, X4 Air, X5, and X6;
  • X5, Ace Pro 2, and Luna I-Log-to-Rec.709 LUTs;
  • the ISO/FOV sharpening parameter file;
  • seven camera-accessory SVM files and five cooling-shell SVM files; and
  • AI-seam, ColorPlus, deflicker, defringe, and JPEG-denoise model payloads.

BundledAssetProvider::manifest() returns the validated manifest. BundledAssetProvider then serves only manifest-declared paths and verifies each requested payload's byte length and SHA-256 digest before returning it:

use insta360_rs::assets::{AssetPolicy, BundledAssetProvider, OpenCvLinearSvm};

fn main() -> insta360_rs::assets::AssetResult<()> {
    let bundle = BundledAssetProvider::manifest()?;
    let asset = bundle
        .load_verified(
            &BundledAssetProvider,
            "camera-accessory-svm-0db3a7a0-xml",
            AssetPolicy::Required,
        )?
        .expect("required bundled asset");
    let svm = OpenCvLinearSvm::parse_xml(&asset.bytes)?;

    println!(
        "{} resources; {} support vectors",
        bundle.assets.len(),
        svm.support_vectors.len()
    );
    Ok(())
}

Applications may alternatively use DirectoryAssetProvider or InMemoryAssetProvider for an application-controlled bundle. Paths are confined below the provider root, and compatibility checks can restrict an asset to a camera, lens ID, and Rust target.

Bundling is not algorithm qualification. Every copied model is unqualified by default. The crate can parse OpenCV linear-SVM payloads and validate complete CoreML/Espresso groups, but it does not yet implement the camera-specific SVM feature extractor, AI seam inference, ColorPlus, deflicker, defringe, or denoise execution. The deterministic stitcher therefore does not silently invoke those resources. An application must qualify the complete preprocessing, inference, and output behavior before selecting a model at runtime.

The project Apache-2.0 license covers project-authored code. The original Insta360 resources retain their vendor licensing, and downstream distributors remain responsible for ensuring that their use and redistribution are covered. See licensed assets, packaging, the literal copy inventory, and NOTICE.md.

Python

The PyO3 package targets Python 3.10+ and exposes probe, blocking packet-preserving extract, capabilities, frame/video export, job polling and cancellation, camera metadata, optical-setup and color-conversion enums, backend selection, and media-acceleration policy. Wheels are not yet release-qualified or published.

When wheels become available, installation will use:

pip install insta360-rs

The distribution name is insta360-rs; import it as insta360_rs:

from insta360_rs import extract

report = extract("recording.insv", "recording-extracted")
print(report.manifest_path, report.stream_count, report.warnings)

Python extraction releases the GIL and uses the same sibling discovery and destination rules as the CLI. Stitched-video calls must currently select AudioPolicy.DROP; extraction still preserves audio packets and attempts a standalone codec-copy remux. The asset-provider layer is not yet exposed as a Python conversion argument.

See Python bindings for examples and wheel targets.

Current limitations

  • High-level media export is restricted to X5 single-file, two-track input.
  • Packed ONE X-X3 video is preserved as one encoded stream; extraction does not synthesize separate decoded lens tracks from that packed frame.
  • V1 calibration is parse-only and fails stitch preflight.
  • Stabilization currently resolves X5 compact raw IMU profiles only. Edited or unsupported recording clocks and unknown sensor transforms fail explicitly.
  • General crop-aware optical projection is not implemented. Sensor readout uses only established crop/rotation conventions; see the stabilization profile.
  • Recorded factory gyro calibration values are retained; their undocumented bias ordering is not guessed. Six-axis fusion cannot remove absolute yaw drift.
  • Input decoding is software-only; GPU output still requires synchronous readback.
  • Stitched video output is 8-bit YUV420 HEVC; extraction preserves encoded 10-bit packets without converting them.
  • Audio copy/remux into stitched MP4 is not implemented; extraction preserves audio packets and attempts a standalone M4A/MKA codec-copy remux.
  • AI seam, ColorPlus, defringe, deflicker, denoise, and accessory-image classification are not runtime capabilities.
  • X1-X4 and X6 need decoded stitching/export support and real-camera golden fixtures; their encoded streams and metadata can already be extracted.
  • Windows D3D12 and Linux Vulkan paths compile but still need real-X5 release qualification.

Documentation

Development

This independent Cargo workspace contains the library, two data crates, and Python bindings. The root [workspace.package] table shares version, author, repository, edition, and minimum Rust version; all members use one Cargo.lock.

From the repository root:

cargo fmt --all -- --check
cargo test --all-features
cargo clippy --workspace --all-targets --all-features -- -D warnings

Media tests require the FFmpeg build environment described under Installation. Some real-media tests run only when their fixture environment variable is configured. The Python binding is built and tested from src-python. Default workspace commands select the library and data crates; run cargo test --locked -p insta360-rs-python to test the bindings separately.

No automated or production path invokes an Insta360 executable or library.

License

Project-authored code is licensed solely under the Apache License, Version 2.0.

See NOTICE.md for trademark and resource-provenance information.

Download files

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

Source Distribution

insta360_rs-0.1.0.tar.gz (29.1 MB view details)

Uploaded Source

Built Distributions

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

insta360_rs-0.1.0-cp310-abi3-win_amd64.whl (37.8 MB view details)

Uploaded CPython 3.10+Windows x86-64

insta360_rs-0.1.0-cp310-abi3-manylinux_2_28_x86_64.whl (37.3 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

insta360_rs-0.1.0-cp310-abi3-macosx_11_0_x86_64.whl (36.7 MB view details)

Uploaded CPython 3.10+macOS 11.0+ x86-64

insta360_rs-0.1.0-cp310-abi3-macosx_11_0_arm64.whl (36.0 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file insta360_rs-0.1.0.tar.gz.

File metadata

  • Download URL: insta360_rs-0.1.0.tar.gz
  • Upload date:
  • Size: 29.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for insta360_rs-0.1.0.tar.gz
Algorithm Hash digest
SHA256 009ce1b8720900ff910c2cdca0b8ea051ffebc4ce5fac642afac47df41096335
MD5 a91ed387c626dbd67c1e439f5818d0d8
BLAKE2b-256 4067b140879520527dd925dfde457a1a1a15ebc51d8a5d8229ee44e8f896bfe4

See more details on using hashes here.

Provenance

The following attestation bundles were made for insta360_rs-0.1.0.tar.gz:

Publisher: release.yml on OpenSpeleo/insta360-rs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file insta360_rs-0.1.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: insta360_rs-0.1.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 37.8 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for insta360_rs-0.1.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 38630b809cb2575791da3b87587cfc5097b4ba9d8b8ac86577091601f96d4c3d
MD5 235f70c91530bd801bfc78c4a3643a9b
BLAKE2b-256 7013d8c14644bf7b0e561c03a6258527a4690a886b4a7ed4e710fb23e88b708d

See more details on using hashes here.

Provenance

The following attestation bundles were made for insta360_rs-0.1.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on OpenSpeleo/insta360-rs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file insta360_rs-0.1.0-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for insta360_rs-0.1.0-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0a749c7cc27916a5374344874aca2f56d30d8ad5b5ec6cfab9d87119920af7b9
MD5 0a9be289831383add75722e63047f636
BLAKE2b-256 88d94bbaebd58924d93a303e99a9985f25cc12360be3d43c273e978c013675df

See more details on using hashes here.

Provenance

The following attestation bundles were made for insta360_rs-0.1.0-cp310-abi3-manylinux_2_28_x86_64.whl:

Publisher: release.yml on OpenSpeleo/insta360-rs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file insta360_rs-0.1.0-cp310-abi3-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for insta360_rs-0.1.0-cp310-abi3-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 9a89929e6d217f3c9eafb0d210256101774a814acbe5295283d0650b61cd8fa8
MD5 2f0d95c01b9c39281534f237ca445311
BLAKE2b-256 44b545c31aa89317dcbf637dba8cd70e4bf09cc0985020d7e8785ffd63ac9619

See more details on using hashes here.

Provenance

The following attestation bundles were made for insta360_rs-0.1.0-cp310-abi3-macosx_11_0_x86_64.whl:

Publisher: release.yml on OpenSpeleo/insta360-rs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file insta360_rs-0.1.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for insta360_rs-0.1.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7587ac0d6beb07eaa52887bec05dea41f72c6e0a54c446c2178f8000cd3a66e7
MD5 34b712d9cd2a50f95545e7e4119ed62b
BLAKE2b-256 34bec9301700fc7491573edad640c22788ec1d9b71b951f4c4c6f447adc678e7

See more details on using hashes here.

Provenance

The following attestation bundles were made for insta360_rs-0.1.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on OpenSpeleo/insta360-rs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

5 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page