VModal SDK: typed video search and streamed uploads for Swift apps
V-Modal Visual Search SDK optimized for IOS Swift and Iphone DUO
At a glance
- What is it?
- VModal for Apple platforms is a Swift package that gives an app semantic search over uploaded video plus streaming uploads with progress and cancellation, while leaving the login screen and the API key entirely to the host app. It is aimed at iOS and macOS apps that need to search their own media library by meaning, speech, text, or imagery.
- Who is it for?
- VModal fits a team building an iOS or macOS app that needs to search video by meaning, spoken words, on-screen text, or imagery, and that wants uploads streamed with progress and cancellation without writing the transport layer. It is the wrong choice if your app cannot reach the VModal service, since the SDK is a client for their gateway, and it is the wrong choice if you need the search to run on device, because the indexing and search happen behind their backend.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 27 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The SDK does the transport and leaves you the interface
VModal for Apple platforms gives iOS and macOS apps a multimodal memory, and the README states the division of labour in one sentence. Your app owns the interface, and the SDK handles the VModal gateway, request models, responses, streaming uploads, progress, and cancellation. That is a narrow surface on purpose, and it is the reason the package is worth a look. You are not adopting a UI kit, a data layer, or a view model framework. You are adopting a typed client, and everything the user sees remains yours. The comparison table in the README makes the same point in user terms, with a cancel button that really cancels backed by per-operation cancellation tokens, and login and account switching done your way, with app-owned runtime credentials and no login UI imposed.
Adding the package is a URL and a product
The SDK reference for getting started lives at `Sources/VModalSDK/VModalSDK.docc/GettingStarted.md`. You add the package in Xcode with File, Add Package Dependencies, using the repository URL, and then attach the `VModalSDK` product to your application target. The toolchain requirements are stated as badges in the README: Swift 6.0, iOS 16 or newer, macOS 13 or newer, and Xcode 26.6 or newer. The repository itself pins this with a `.swift-version` and a `.xcode-version` file at the root, alongside a `Package.swift`, so the declared floors and the actual build configuration are visible in the tree. The licence is MIT, with the LICENSE file at the repository root, which makes the dependency straightforward to include in a commercial app.
Configuration is a provider, a project, and an immutable scope
The first use creates one project and one scope, and the shape of the API makes the intent clear. You create a provider from the API key your authenticated app already loaded, then configure a project with it, then take a scope:
import VModalSDK
let keys = try MutableAPIKeyProvider("runtime-api-key")
let project = try VModal.configure(
projectID: "food_app",
apiKeyProvider: keys
)
let favorites = try project.scope(
collectionName: "user_123",
streamName: "favorites"
)The naming rules are enforced rather than documented and hoped for. `projectID`, `collectionName`, and `streamName` accept only letters, digits, and the `_` character, each is trimmed and limited to 80 characters, and project and collection names cannot contain the reserved `__` separator, with the encoded backend value also limited to 80 characters and the encoding handled internally by the SDK. The scopes are immutable, so a scope is a handle you keep and reuse rather than a mutable session. The README also states the separation that matters for authentication design: the SDK never owns your login screen or persists your API key, and authentication identity is separate from project, collection, and stream organization.
Search is scoped, typed, and can return a 404 that is not a server fault
Search takes a natural language query and a set of options, including which sources to search and a result limit:
let results = try await favorites.search(
"the cyclist crossing the bridge at sunset",
options: ScopedSearchOptions(
searchSources: ["image"],
limit: 20
)
)The sources are AUDIO and TEXT for spoken words and on-screen text, and image for visual similarity, which is what makes a query like finding the cyclist in the red jacket work. The README also names a failure mode worth internalising. Collection access is key-scoped, so a logical name copied from another account or environment can return HTTP 404 even when the search route is healthy. That is a confusing error to debug from the outside, and the documentation flags it directly. There is also `ScopedSearchOptions(versionLancedb: version)` for applications that track a specific index version. On the response side, the contract is typed where it is stable and the raw JSON is preserved, so new server fields remain available immediately without waiting for an SDK update.
Uploads stream from a file URL rather than loading the file
The upload path is the part with the most engineering behind it, and the first line of the README's section is a constraint rather than a feature. The SDK reads an app-accessible file URL as a stream, and it does not load the entire video into memory. On a phone recording hours of footage, that is the difference between a working feature and an out of memory crash, and it is why the source type is a file URL rather than a Data value. The API returns an upload handle with a progress stream and a result, and a cancel method:
let source = try UploadSource(fileURL: movieURL)
let upload = favorites.upload(source)
let progress = Task {
for await value in upload.progress {
print("Uploading \(value.percent)%")
}
}
let uploaded = try await upload.result
progress.cancel()
print("Ready: \(uploaded.filename)")The pattern is a Swift concurrency one worth copying. The progress values arrive on an async sequence consumed by a Task, while the result is awaited separately, and the progress task is cancelled once the result arrives so it does not leak.
CCTV footage gets a filename and an origin, and the backend normalizes the time
For surveillance and street video archives, the SDK provides `VideoUploadOptions` for the public filename and an offset-aware recording origin, and the README is explicit about where the time handling lives. The backend, not the SDK, normalizes the datetime and returns canonical UTC epoch milliseconds. Metadata tags are repeated independently on the wire. That division is worth understanding before you build a timeline on top of it. If your app's own records use a local time zone, or if your camera clocks drift, the canonical value the backend returns is the one to store, and the offset-aware origin is what lets the service reconcile a recording that started before the clip began. The repository ships a product example for this case, `example/05_framebase`, described as browsing, preparing, searching, and playing a local street video archive, which is a better way to understand the API than the reference alone.
The repository ships a starter app and a script-driven workflow
The Getting Started section is written for a coding agent rather than a human, and it is unusual enough to be worth describing. The README asks you to copy a prompt into your coding agent, and the prompt tells the agent to clone the repository, inspect the repository instructions and `example/StarterIOS/README.md`, use the repository's selected Xcode and Swift toolchain without installing or switching Xcode, and then run a series of scripts: `bash install.sh check`, `bash build.sh analyze`, and `bash test.sh test`. It continues with `bash install.sh device_list` to list devices and `bash install.sh device_id` to get the first available iPhone simulator identifier, and `bash run.sh example --device DEVICE_ID` to run the example on it. The prompt closes with strict boundaries. Do not hard-code credentials or persist an API key, and if a required Xcode installation, simulator, or API key is unavailable, stop at that boundary and report the exact blocker. That last instruction is a good model for how the project expects to be driven.
Maintenance, tooling, and the shape of the repository
The repository is laid out like a serious SDK rather than a sample. At the root there are `install.sh`, `build.sh`, `test.sh`, `run.sh`, and `cli.sh` for the workflow above, plus `env.sh`, `security_check.sh`, and a `.gitleaks.toml` for secret scanning. There is a `00_specs.md` at the root, a `CHANGELOG.md`, a `RELEASE_METADATA` file, and a `SOURCE_MANIFEST.sha256`, which together suggest the release is reproducible and verifiable. `Tools/`, `Sources/`, `Tests/`, `docs/`, `release/`, and the `example/` directory with `StarterIOS` and `05_framebase` complete the picture. The licence is MIT, the last push was on 2026-09-26, and the repository has no GitHub releases, so the CHANGELOG and the version pinning in `Package.swift` are what you track. Support runs through a Discord, with a Reddit community at r/v_modal, and API keys are requested from VModal directly rather than self-served, so there is a vendor relationship behind the SDK even though the client code is open.
Editorial conclusion
VModal fits a team building an iOS or macOS app that needs to search video by meaning, spoken words, on-screen text, or imagery, and that wants uploads streamed with progress and cancellation without writing the transport layer. It is the wrong choice if your app cannot reach the VModal service, since the SDK is a client for their gateway, and it is the wrong choice if you need the search to run on device, because the indexing and search happen behind their backend. Before you adopt it, read the Getting Started reference in `Sources/VModalSDK/VModalSDK.docc`, decide where the API key lives, since the SDK never persists it, and pin the toolchain the repository expects, with Swift 6.0, iOS 16, macOS 13, and Xcode 26.6 as the stated floors.
Frequently asked questions
How do I add the VModal SDK to an Xcode project?
Use File, Add Package Dependencies in Xcode with the repository URL, then attach the `VModalSDK` product to your application target. The stated requirements are Swift 6.0, iOS 16 or newer, macOS 13 or newer, and Xcode 26.6 or newer.
Does the VModal SDK store my API key?
No. The README states the SDK never owns your login screen or persists your API key, and that authentication identity is separate from project, collection, and stream organization. Your app supplies the key at runtime through an API key provider.
What search sources can the VModal SDK query?
The README lists AUDIO and TEXT search sources for words spoken or shown on screen, and image search for visual similarity. The source list is passed per query through options such as `searchSources`.
Why does a VModal search sometimes return HTTP 404?
Collection access is key-scoped, so a logical name copied from another account or environment can return HTTP 404 even when the search route is healthy. Use `ScopedSearchOptions(versionLancedb: version)` if your application tracks a specific index version.
How are large video uploads handled by the VModal SDK?
The SDK reads an app-accessible file URL as a stream and does not load the entire video into memory. It exposes a progress stream for live percentage updates, per-operation cancellation tokens, and an awaited result. For CCTV footage you can supply `VideoUploadOptions` with a public filename and an offset-aware recording origin, and the backend normalizes the datetime to UTC epoch milliseconds.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/v-modal-vmodal-sdk-swift-iphoneduo)Was this useful?