[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-93440":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":17,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":9,"rankLanguage":9,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":15,"starSnapshotCount":15,"syncStatus":12,"lastSyncTime":28,"discoverSource":29},93440,"vmodal_sdk_flutter","v-modal\u002Fvmodal_sdk_flutter","v-modal","V- Modal AI: Search anything anywhere SDK Flutter",null,"Dart",819,2,152,1,0,104,570,777,94.9,"MIT License",false,"main",true,[],"2026-07-22 04:02:09","\u003Cdiv align=\"center\">\n  \u003Cimg src=\"readme_assets\u002Flogo_vmodal_owl.jpeg\" alt=\"VModal owl\" width=\"96\">\n  \u003Ch1>VModal for Flutter\u003C\u002Fh1>\n  \u003Cp>\u003Cstrong>Give your Android and iOS apps a multimodal memory.\u003C\u002Fstrong>\u003C\u002Fp>\n  \u003Cp>Upload video. Find moments by meaning, speech, text, or imagery.\u003Cbr>Keep the experience fast, native, and 100% Flutter.\u003C\u002Fp>\n  \u003Cimg src=\"https:\u002F\u002Fflutter.dev\u002Fassets\u002Flockup_built-w-flutter.5443036ead976e7afea9249e17cd32b3.svg\" alt=\"Built with Flutter\" width=\"210\">\n  \u003Cbr>\u003Cbr>\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FFlutter-3.44%2B-02569B?logo=flutter&logoColor=white\" alt=\"Flutter 3.44+\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDart-3.12%2B-0175C2?logo=dart&logoColor=white\" alt=\"Dart 3.12+\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FAndroid-supported-3DDC84?logo=android&logoColor=white\" alt=\"Android supported\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FiOS-supported-000000?logo=apple&logoColor=white\" alt=\"iOS supported\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-MIT-6C63FF\" alt=\"MIT license\">\n\u003C\u002Fdiv>\n\n\u003Cbr>\n\n\u003Cimg src=\"readme_assets\u002Fdev_homepage.jpg\" alt=\"A wall of searchable video moments and developer screens\" width=\"100%\">\n\n\u003Cp align=\"center\">\u003Cem>Turn every video library into an experience your users can explore.\u003C\u002Fem>\u003C\u002Fp>\n\n## Build the feature people remember\n\nVModal brings multimodal video search and mobile-friendly uploads to Dart with a small, typed API. Your app owns the interface; the SDK handles the VModal gateway, request models, responses, upload streams, progress, and cancellation.\n\n| Your Flutter experience | VModal gives you |\n|---|---|\n| “Find the cyclist in the red jacket” | Semantic video and image search |\n| Search words spoken or shown on screen | ASR and OCR search sources |\n| Upload from a picker or camera flow | Streamed, signed uploads with live progress |\n| A cancel button that really cancels | Per-operation cancellation tokens |\n| Collection and indexing screens | Typed collection, index, usage, and image resources |\n| Login and account switching your way | App-owned runtime credentials—no login UI imposed |\n\n## Start in minutes\n\nThe public package source is available on GitHub. Add it to your app:\n\n```yaml\ndependencies:\n  vmodal_sdk_flutter:\n    git:\n      url: https:\u002F\u002Fgithub.com\u002Fv-modal\u002Fvmodal_sdk_flutter.git\n      ref: main\n```\n\nThen run:\n\n```bash\nflutter pub get\n```\n\nCreate one client from the API key already loaded by your authenticated app:\n\n```dart\nimport 'package:vmodal_sdk_flutter\u002Fvmodal_sdk_flutter.dart';\n\nfinal keys = MutableApiKeyProvider(runtimeApiKey);\nfinal vmodal = VmodalClient(\n  config: SdkConfig(apiKeyProvider: keys),\n);\n```\n\n> The SDK never owns your login screen or persists your API key. It receives an in-memory credential from your application at runtime.\n\n## Search video with natural language\n\n```dart\nfinal groups = await vmodal.collections.listGroups(mode: 'vid_file');\nif (groups.data.isEmpty) {\n  throw StateError('No video collection exists for this API key');\n}\nfinal group = groups.data.first;\nfinal version = group.latestLancedbVersion;\nif (version == null) {\n  throw StateError('The collection has no searchable LanceDB version');\n}\n\nfinal results = await vmodal.searches.searchVideo(\n  SearchRequest(\n    queryText: 'the cyclist crossing the bridge at sunset',\n    groupName: group.groupName,\n    searchSources: const ['image'],\n    versionLancedb: version,\n    limit: 20,\n  ),\n);\n\nprint('${results.cntActual} moments found');\nfor (final moment in results.data) {\n  print(moment);\n}\n```\n\nThe collection must be a `vid_file` `GroupItem` returned\nfor the current runtime API key. Collection access is key-scoped; a name copied\nfrom another account or environment can return HTTP 404 even when the search\nroute is healthy. The example name `flutter_example` is valid only after that\nkey has uploaded or otherwise created the collection and a refreshed\n`listGroups()` response contains it. Search must also send an advertised\n`lancedbVersions` value; `latestLancedbVersion` converts values such as `v1`\nto the numeric request field `version_lancedb: 1`.\n\nThe response stays typed where the contract is stable and preserves the raw JSON so new server fields remain available immediately.\n\n## Upload with progress and cancellation\n\nThe SDK reads an app-accessible `File` as a stream. It does not load the entire video into memory.\n\n```dart\nimport 'dart:io';\n\nfinal task = vmodal.collections.videoUpload(\n  UploadSource.fromFile(File(videoPath)),\n  collectionName: 'travel_diaries',\n  subCollectionName: 'mobile_uploads',\n);\n\nfinal progress = task.progress.listen((value) {\n  print('Uploading ${value.percent}%');\n});\n\n\u002F\u002F Connect this to your Flutter cancel button when needed:\n\u002F\u002F task.cancel();\n\nfinal uploaded = await task.result;\nawait progress.cancel();\nprint('Ready: ${uploaded.fileName}');\n```\n\nSigned single upload is the production default for every file size. Multipart upload is experimental and must be enabled explicitly with `VideoUploadOptions(multipart: true)`; it fails with `FeatureDisabled` when the complete backend route family is unavailable.\n\n## Designed for real mobile lifecycles\n\n- Rotate credentials without rebuilding the client: `keys.rotate(newApiKey)`.\n- Cancel search or upload work when a screen closes.\n- Show upload progress from a broadcast Dart stream.\n- Keep file picking, secure storage, background scheduling, and lifecycle UI in the parent app.\n- Close network resources deterministically with `await vmodal.close()`.\n\nFor logout or account switching, cancel active work, clear upload persistence, call `keys.clear()`, close the client, and create a new client for the next identity. Key rotation alone is not an identity switch.\n\n## One client, focused resources\n\n```text\nvmodal.auth          identity and health\nvmodal.searches      multimodal video search\nvmodal.collections   upload and collection lifecycle\nvmodal.indexes       create, inspect, and delete indexes\nvmodal.admin         usage and cache statistics\nvmodal.r2            presigned object-storage operations\nvmodal.images        image retrieval\n```\n\nGateway mode is the safe default and sends caller identity only as a bearer credential. `VmodalClient.unsafeDirect` is reserved for trusted private networks.\n\n## Platform support\n\n| Platform | Status | Notes |\n|---|---:|---|\n| Android | ✅ Supported | Flutter-native Dart API |\n| iOS | ✅ Supported | Flutter-native Dart API |\n| Flutter Web | ⛔ Not supported | Not part of the 1.0 release contract |\n| macOS, Windows, Linux | ⏳ Not targeted | Mobile-first release |\n\nMinimum toolchain: Flutter `3.44.0` and Dart `3.12.0`.\n\n## Explore the SDK\n\n- [Browse the public SDK reference](https:\u002F\u002Fv-modal.github.io\u002Fvmodal_sdk_flutter\u002F)\n- [Run the complete example app](https:\u002F\u002Fgithub.com\u002Fv-modal\u002Fvmodal_sdk_flutter\u002Ftree\u002Fmain\u002Fexample)\n- [Read the SDK guide](https:\u002F\u002Fgithub.com\u002Fv-modal\u002Fvmodal_sdk_flutter\u002Fblob\u002Fmain\u002Fdoc\u002Fsdk_doc.md)\n- [Manage API keys safely](https:\u002F\u002Fgithub.com\u002Fv-modal\u002Fvmodal_sdk_flutter\u002Fblob\u002Fmain\u002Fdoc\u002Fmanage_api_key.md)\n- [Build a search experience](https:\u002F\u002Fgithub.com\u002Fv-modal\u002Fvmodal_sdk_flutter\u002Fblob\u002Fmain\u002Fdoc\u002Fsearch_app.md)\n- [Review the API contract](https:\u002F\u002Fgithub.com\u002Fv-modal\u002Fvmodal_sdk_flutter\u002Fblob\u002Fmain\u002Fdoc\u002Fsdk_contract.md)\n- [Open an issue](https:\u002F\u002Fgithub.com\u002Fv-modal\u002Fvmodal_sdk_flutter\u002Fissues)\n\n## Development\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fv-modal\u002Fvmodal_sdk_flutter.git\ncd vmodal_sdk_flutter\nbash install.sh install\nbash test.sh all\n```\n\nThe offline gate analyzes the package, runs the SDK and example tests, checks route synchronization, and validates Android\u002FiOS example builds. Live tests require the repository's existing test credentials and are intentionally separate.\n\n---\n\n\u003Cp align=\"center\">\u003Cstrong>Build video experiences people can search, not just scroll.\u003C\u002Fstrong>\u003C\u002Fp>\n\n\u003Csub>Flutter and the related logo are trademarks of Google LLC. VModal is not endorsed by or affiliated with Google LLC.\u003C\u002Fsub>\n","VModal for Flutter 是一个为跨平台移动应用提供多模态视频搜索能力的 SDK。它支持通过自然语言、语音转文字（ASR）、光学字符识别（OCR）及图像语义理解，在本地或云端视频库中精准检索特定时刻，同时提供流式上传、进度反馈与操作取消等原生体验。SDK 采用 Dart 编写，深度适配 Flutter 框架，不接管 UI 或认证流程，由应用自主控制界面与凭证管理。适用于需要在移动端快速集成智能视频检索功能的产品，如教育回放、会议记录、监控片段查找、短视频内容导航等场景。","2026-07-18 02:30:07","CREATED_QUERY"]