feat: add multimodal search and granular performance diagnostics
Core CI / core (ubuntu-latest) (push) Failing after 3m31s
Core CI / core (macos-latest) (push) Canceled after 0s
Core CI / core (windows-latest) (push) Canceled after 0s
Core CI / desktop (ubuntu-latest) (push) Successful in 5m39s
Core CI / desktop (macos-latest) (push) Canceled after 0s
Core CI / desktop (windows-latest) (push) Canceled after 0s

This commit is contained in:
karl committed 2026-10-12 19:16:23 +02:00
1 parent d3bb8c7618
commit b8400c4fbf
110 files changed
+79395 -250

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
# Standalone media decoder tools
The desktop distribution must include FFmpeg and FFprobe alongside its Google
worker. End users should not install tools or configure paths. Development and
release preparation use:
```sh
python tools/media-runtime/provision.py --stage
python -m unittest discover -s tools/media-runtime -p 'test_*.py'
```
The manifest pins a dated BtbN release, exact archive size, and published SHA-256.
Provisioning checks the cache or downloads/verifies the archive, extracts only the
two standalone decoder executables and notices, and stages them under the native
resources directory. Executables and archives are ignored by Git. No global
installation occurs. Movie/audio decoding runs in bounded subprocesses.
Windows x86-64/ARM64 and Linux x86-64/ARM64 have pinned artifacts. Only Windows
x86-64 has been executed here. A vetted macOS decoder build/staging path remains
a release gate; generic media code can accept native tools through explicit paths.
The selected build is FFmpeg 9.0.2 with LGPL configuration. Keep original notices
and corresponding source/build provenance with distribution; installer licensing
and all-platform execution are still open production gates.
Source/build provenance:
- https://github.com/BtbN/FFmpeg-Builds/releases/tag/autobuild-2026-10-12-13-12
- https://github.com/BtbN/FFmpeg-Builds
- https://ffmpeg.org/legal.html
FFmpeg capabilities vary by build. An unsupported or corrupt file must report an
error while remaining filename-searchable; it must never freeze search or be
silently reported as fully indexed.
+27
View File
@@ -0,0 +1,27 @@
{
"provider": "BtbN/FFmpeg-Builds",
"release": "autobuild-2026-10-12-13-12",
"version": "9.0.2-27-g7e93014c5b",
"platforms": {
"windows-x86_64": {
"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-win64-lgpl-9.0.zip",
"bytes": 171476229,
"sha256": "104a019fe34c0747b208bde4842a0bac8b70a307cc2bb33aa4648fc15ddb2e39"
},
"windows-aarch64": {
"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-winarm64-lgpl-9.0.zip",
"bytes": 118006941,
"sha256": "68d3bac585b80b6f17e459eb4a203ed1f01b7635d4c611f1685de1ae65ca0987"
},
"linux-x86_64": {
"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-linux64-lgpl-9.0.tar.xz",
"bytes": 137901812,
"sha256": "12445b38a4700ba1ae7c9c7e57062f602c927dc4187555bfadc9f3e2f75f05b0"
},
"linux-aarch64": {
"archive": "ffmpeg-n9.0.2-27-g7e93014c5b-linuxarm64-lgpl-9.0.tar.xz",
"bytes": 117008524,
"sha256": "c9160ae8440c17c016fb2f6b3fcce4bb9d633a15845e908b2303948a7724f227"
}
}
}
+128
View File
@@ -0,0 +1,128 @@
"""Verify and stage standalone FFmpeg tools. No user-wide installation or GPU use."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import platform
import shutil
import tarfile
import tempfile
import urllib.request
import zipfile
ROOT = Path(__file__).resolve().parents[2]
MAX_MEMBER = 256 * 1024 * 1024
def verified(path, artifact):
if not path.is_file() or path.stat().st_size != artifact["bytes"]:
return False
with path.open("rb") as stream:
return hashlib.file_digest(stream, "sha256").hexdigest() == artifact["sha256"]
def install(stream, target, expected):
if not 0 < expected <= MAX_MEMBER:
raise ValueError("Archive member exceeds size ceiling")
target.parent.mkdir(parents=True, exist_ok=True)
temporary = target.with_suffix(target.suffix + ".partial")
try:
with temporary.open("wb") as output:
copied = 0
while block := stream.read(65536):
copied += len(block)
if copied > expected:
raise ValueError("Archive member exceeds declared length")
output.write(block)
if copied != expected:
raise ValueError("Archive member is truncated")
if target.name in {"ffmpeg", "ffprobe"}:
temporary.chmod(0o755)
os.replace(temporary, target)
finally:
temporary.unlink(missing_ok=True)
def extract(archive, destination, windows):
required = {"ffmpeg.exe", "ffprobe.exe"} if windows else {"ffmpeg", "ffprobe"}
found = set()
def target_for(name):
# Never extract arbitrary paths: selected basenames map to fixed targets.
basename = name.replace("\\", "/").split("/")[-1]
if basename in required:
if basename in found:
raise ValueError("Duplicate decoder executable")
found.add(basename)
return destination / "bin" / basename
if basename.lower().startswith(("license", "copying")) or basename.lower() in {"readme.txt", "readme.md"}:
parts = name.replace("\\", "/").split("/")
if any(part in {".", "..", ""} or ":" in part for part in parts):
raise ValueError("Unsafe notice path")
return destination / "licenses" / Path(*parts)
return None
if archive.suffix == ".zip":
with zipfile.ZipFile(archive) as package:
for member in package.infolist():
target = target_for(member.filename)
if target is not None and not member.is_dir():
with package.open(member) as stream:
install(stream, target, member.file_size)
else:
with tarfile.open(archive, "r:xz") as package:
for member in package:
target = target_for(member.name)
if target is not None:
if not member.isfile():
raise ValueError("Selected archive member is not a regular file")
with package.extractfile(member) as stream:
install(stream, target, member.size)
if found != required:
raise ValueError("Archive is missing required decoder tools")
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--stage", action="store_true", help="Copy verified decoder tools and notices into Tauri resources")
args = parser.parse_args()
manifest = json.loads(Path(__file__).with_name("manifest.json").read_text())
machine = platform.machine().lower()
architecture = "aarch64" if machine in {"arm64", "aarch64"} else "x86_64" if machine in {"amd64", "x86_64"} else machine
system = platform.system().lower()
key = f"{system}-{architecture}"
if key not in manifest["platforms"]:
raise RuntimeError(f"No verified decoder artifact for {key}; macOS packaging remains a release gate")
artifact = manifest["platforms"][key]
directory = ROOT / ".searchi/media-runtime"
directory.mkdir(parents=True, exist_ok=True)
archive = directory / artifact["archive"]
if not verified(archive, artifact):
url = f"https://github.com/{manifest['provider']}/releases/download/{manifest['release']}/{artifact['archive']}"
with tempfile.NamedTemporaryFile(dir=directory, delete=False) as output:
temporary = Path(output.name)
try:
with urllib.request.urlopen(urllib.request.Request(url, headers={"User-Agent": "searchi-runtime-setup"}), timeout=120) as response:
copied = 0
while block := response.read(65536):
copied += len(block)
if copied > artifact["bytes"]:
raise ValueError("Decoder download exceeds manifest size")
output.write(block)
output.close()
if not verified(temporary, artifact):
raise ValueError("Decoder size/SHA-256 mismatch")
os.replace(temporary, archive)
finally:
output.close()
temporary.unlink(missing_ok=True)
extract(archive, directory, system == "windows")
if args.stage:
destination = ROOT / "apps/desktop/src-tauri/resources/media-runtime"
shutil.copytree(directory / "bin", destination / "bin", dirs_exist_ok=True)
shutil.copytree(directory / "licenses", destination / "licenses", dirs_exist_ok=True)
shutil.copy2(Path(__file__).with_name("manifest.json"), destination / "manifest.json")
print(f"Verified media tools available at {directory / 'bin'}")
if __name__ == "__main__":
main()
+60
View File
@@ -0,0 +1,60 @@
import hashlib
import importlib.util
from pathlib import Path
import tempfile
import unittest
import zipfile
spec = importlib.util.spec_from_file_location("media_provision", Path(__file__).with_name("provision.py"))
provision = importlib.util.module_from_spec(spec)
spec.loader.exec_module(provision)
class ProvisionTests(unittest.TestCase):
def package(self, directory, entries):
archive = directory / "sample.zip"
with zipfile.ZipFile(archive, "w") as package:
for name, data in entries:
package.writestr(name, data)
return archive
def test_selects_only_tools_and_preserves_distinct_notices(self):
with tempfile.TemporaryDirectory() as temporary:
directory = Path(temporary)
archive = self.package(directory, [("build/bin/ffmpeg.exe", b"tool1"),
("build/bin/ffprobe.exe", b"tool2"), ("build/README.txt", b"readme"),
("build/LICENSE", b"first license"), ("build/dependency/LICENSE", b"second license"),
("../../unselected.exe", b"unselected")])
target = directory / "out"
provision.extract(archive, target, True)
self.assertEqual((target / "bin/ffmpeg.exe").read_bytes(), b"tool1")
self.assertEqual(len(list((target / "licenses").rglob("LICENSE"))), 2)
self.assertFalse((directory / "unselected.exe").exists())
def test_missing_and_duplicate_executables_are_explicit_failures(self):
with tempfile.TemporaryDirectory() as temporary:
directory = Path(temporary)
for entries in [[("bin/ffmpeg.exe", b"tool")],
[("a/ffmpeg.exe", b"tool"), ("b/ffmpeg.exe", b"second"), ("bin/ffprobe.exe", b"probe")]]:
with self.assertRaises(ValueError):
provision.extract(self.package(directory, entries), directory / "out", True)
def test_same_size_corruption_is_not_a_verified_cache(self):
with tempfile.TemporaryDirectory() as temporary:
path = Path(temporary) / "archive"
path.write_bytes(b"good")
artifact = {"bytes": 4, "sha256": hashlib.sha256(b"good").hexdigest()}
self.assertTrue(provision.verified(path, artifact))
path.write_bytes(b"evil")
self.assertFalse(provision.verified(path, artifact))
def test_notice_traversal_cannot_escape_output(self):
with tempfile.TemporaryDirectory() as temporary:
directory = Path(temporary)
archive = self.package(directory, [("../../LICENSE", b"escape")])
with self.assertRaises(ValueError):
provision.extract(archive, directory / "out", True)
if __name__ == "__main__":
unittest.main()