Add Windows ARM 64 Native Build Support (#85)

* [CI] Add Windows ARM 64 GitHub builds

* Use a patched generator-rs for Windows ARM support

* Fix download url for ffmpeg on ARM64

* Replace reversegeocoder with more multi platform compatible rstar

* [CI] Point back to official ffmpeg repo

* Clear article bundle cache for pr linux and mac builds

---------

Co-authored-by: Joseph Gershgorin <jgershgorin@biocentury.com>
This commit is contained in:
talynone
2026-04-25 11:26:31 +08:00
committed by GitHub
co-authored by Joseph Gershgorin
parent bb62225a44
commit 9774293b95
8 changed files with 144884 additions and 268 deletions
+35 -15
View File
@@ -108,6 +108,10 @@ jobs:
shell: bash
run: bash scripts/download_models.sh
- name: Clear cached macOS bundle artifacts
shell: bash
run: rm -rf "src-tauri/target/${{ matrix.target }}/release/bundle"
- name: Build and Sign
uses: tauri-apps/tauri-action@v0.5
env:
@@ -181,7 +185,19 @@ jobs:
if: |
(github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'windows')) ||
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
runs-on: windows-latest
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: windows-latest
target: x86_64-pc-windows-msvc
msvc_arch: x64
- arch: arm64
runner: windows-11-arm
target: aarch64-pc-windows-msvc
msvc_arch: arm64
steps:
- name: Checkout repository
@@ -209,14 +225,14 @@ jobs:
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: windows-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
key: windows-${{ matrix.arch }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
windows-pnpm-store-
windows-${{ matrix.arch }}-pnpm-store-
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc
targets: ${{ matrix.target }}
- name: Cache Rust dependencies
uses: actions/cache@v4
@@ -227,9 +243,9 @@ jobs:
~\.cargo\registry\cache\
~\.cargo\git\db\
src-tauri\target\
key: windows-x86_64-cargo-${{ hashFiles('**/Cargo.lock') }}
key: windows-${{ matrix.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
windows-x86_64-cargo-
windows-${{ matrix.arch }}-cargo-
- name: Install frontend dependencies
working-directory: src-vite
@@ -250,21 +266,21 @@ jobs:
- name: Setup MSVC build environment
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
arch: ${{ matrix.msvc_arch }}
- name: Clear cached Windows bundle artifacts
shell: pwsh
run: |
$bundleDir = "src-tauri/target/x86_64-pc-windows-msvc/release/bundle"
$bundleDir = "src-tauri/target/${{ matrix.target }}/release/bundle"
if (Test-Path $bundleDir) {
Remove-Item -Recurse -Force $bundleDir
}
- name: Download FFmpeg Sidecars (Windows)
shell: pwsh
run: .\scripts\download_ffmpeg_sidecar.ps1
run: .\scripts\download_ffmpeg_sidecar.ps1 -Arch ${{ matrix.arch }}
- name: Build and Sign (Windows x64)
- name: Build and Sign (Windows ${{ matrix.arch }})
uses: tauri-apps/tauri-action@v0.5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -273,13 +289,13 @@ jobs:
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: .
args: --verbose --target x86_64-pc-windows-msvc --bundles msi --config '{"bundle":{"createUpdaterArtifacts":false}}'
args: --verbose --target ${{ matrix.target }} --bundles msi --config '{"bundle":{"createUpdaterArtifacts":false}}'
- name: Rename Windows package for PR build
shell: pwsh
run: |
$suffix = "pr-${{ github.event.pull_request.number || github.run_number }}"
$msi = Get-ChildItem -Path "src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi" -Filter "*.msi" -File | Select-Object -First 1
$msi = Get-ChildItem -Path "src-tauri/target/${{ matrix.target }}/release/bundle/msi" -Filter "*.msi" -File | Select-Object -First 1
if (-not $msi) {
throw "Could not find generated MSI file."
}
@@ -296,10 +312,10 @@ jobs:
- name: Upload Windows artifacts
uses: actions/upload-artifact@v4
with:
name: lap-pr-windows-x64-${{ github.event.pull_request.number || github.run_number }}
name: lap-pr-windows-${{ matrix.arch }}-${{ github.event.pull_request.number || github.run_number }}
path: |
src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/*.msi
src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/*.msi.sig
src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi
src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig
if-no-files-found: error
build-linux:
@@ -373,6 +389,10 @@ jobs:
shell: bash
run: bash scripts/download_models.sh
- name: Clear cached Linux bundle artifacts
shell: bash
run: rm -rf src-tauri/target/x86_64-unknown-linux-gnu/release/bundle
- name: Build and Sign
uses: tauri-apps/tauri-action@v0.5
env:
+108 -45
View File
@@ -7,13 +7,55 @@ on:
description: "Existing release tag to publish Windows assets to"
required: true
type: string
build_target:
description: "Architecture to build"
required: false
default: "all"
type: choice
options:
- all
- x64
- arm64
permissions:
contents: write
jobs:
setup:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
shell: bash
run: |
set -euo pipefail
ALL='[
{"arch":"x64","runner":"windows-latest","target":"x86_64-pc-windows-msvc","msvc_arch":"x64","platform_key":"windows-x86_64","artifact_name":"windows-x86_64","msi_glob":"*_x64_*.msi"},
{"arch":"arm64","runner":"windows-11-arm","target":"aarch64-pc-windows-msvc","msvc_arch":"arm64","platform_key":"windows-aarch64","artifact_name":"windows-aarch64","msi_glob":"*_arm64_*.msi"}
]'
INPUT="${{ github.event.inputs.build_target }}"
if [ -z "$INPUT" ] || [ "$INPUT" = "all" ]; then
SEL="$ALL"
else
SEL=$(echo "$ALL" | jq -c --arg a "$INPUT" '[.[] | select(.arch == $a)]')
if [ "$SEL" = "[]" ]; then
echo "Unknown build_target: $INPUT"
exit 1
fi
fi
MATRIX=$(echo "$SEL" | jq -c '{include: .}')
echo "Generated matrix: $MATRIX"
echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT"
build-windows:
runs-on: windows-latest
needs: setup
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
steps:
- name: Checkout repository
@@ -40,14 +82,14 @@ jobs:
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: windows-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
key: windows-${{ matrix.arch }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
windows-pnpm-store-
windows-${{ matrix.arch }}-pnpm-store-
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc
targets: ${{ matrix.target }}
- name: Cache Rust dependencies
uses: actions/cache@v4
@@ -58,9 +100,9 @@ jobs:
~\.cargo\registry\cache\
~\.cargo\git\db\
src-tauri\target\
key: windows-x86_64-cargo-${{ hashFiles('**/Cargo.lock') }}
key: windows-${{ matrix.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
windows-x86_64-cargo-
windows-${{ matrix.arch }}-cargo-
- name: Install frontend dependencies
working-directory: src-vite
@@ -81,22 +123,21 @@ jobs:
- name: Setup MSVC build environment
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
arch: ${{ matrix.msvc_arch }}
- name: Clear cached Windows bundle artifacts
shell: pwsh
run: |
$bundleDir = "src-tauri/target/x86_64-pc-windows-msvc/release/bundle"
$bundleDir = "src-tauri/target/${{ matrix.target }}/release/bundle"
if (Test-Path $bundleDir) {
Remove-Item -Recurse -Force $bundleDir
}
- name: Download FFmpeg Sidecars (Windows)
shell: pwsh
run: .\scripts\download_ffmpeg_sidecar.ps1
run: .\scripts\download_ffmpeg_sidecar.ps1 -Arch ${{ matrix.arch }}
- name: Build and Sign (Windows x64)
- name: Build and Sign (Windows ${{ matrix.arch }})
uses: tauri-apps/tauri-action@v0.5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -105,15 +146,15 @@ jobs:
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: .
args: --verbose --target x86_64-pc-windows-msvc --bundles msi
args: --verbose --target ${{ matrix.target }} --bundles msi
- name: Upload Build Artifact (Windows)
- name: Upload Build Artifact (Windows ${{ matrix.arch }})
uses: actions/upload-artifact@v4
with:
name: windows-x86_64
name: ${{ matrix.artifact_name }}
path: |
src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/*.msi
src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/*.msi.sig
src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi
src-tauri/target/${{ matrix.target }}/release/bundle/msi/*.msi.sig
if-no-files-found: error
publish-windows:
@@ -124,8 +165,9 @@ jobs:
- name: Download Windows artifacts
uses: actions/download-artifact@v4
with:
name: windows-x86_64
pattern: windows-*
path: release-files
merge-multiple: true
- name: Show release files
run: ls -la release-files
@@ -156,7 +198,7 @@ jobs:
echo "Timed out waiting for latest.json on release $TAG."
exit 1
- name: Update latest.json with Windows updater entry
- name: Update latest.json with Windows updater entries
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
@@ -164,20 +206,8 @@ jobs:
set -euo pipefail
TAG="${{ github.event.inputs.release_tag }}"
VERSION="${TAG#v}"
MSI_FILE="$(find release-files -maxdepth 1 -name '*.msi' | head -n 1)"
MSI_SIG_FILE="$(find release-files -maxdepth 1 -name '*.msi.sig' | head -n 1)"
if [ -z "${MSI_FILE}" ] || [ ! -f "${MSI_FILE}" ]; then
echo "No MSI installer (*.msi) found."
exit 1
fi
if [ -z "${MSI_SIG_FILE}" ] || [ ! -f "${MSI_SIG_FILE}" ]; then
echo "Missing MSI updater signature file (*.msi.sig)."
exit 1
fi
MSI_NAME="$(basename "${MSI_FILE}")"
WINDOWS_SIG="$(cat "${MSI_SIG_FILE}")"
REPO="${{ github.repository }}"
PUB_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
rm -f release-files/latest.json
gh release download "$TAG" -R "$GH_REPO" -p "latest.json" -D release-files >/dev/null 2>&1
@@ -186,19 +216,52 @@ jobs:
exit 1
fi
tmp="$(mktemp)"
jq \
--arg version "${VERSION}" \
--arg pub_date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg sig "${WINDOWS_SIG}" \
--arg url "https://github.com/${{ github.repository }}/releases/download/${TAG}/${MSI_NAME}" \
'
.version = $version
| .pub_date = $pub_date
| .platforms = (.platforms // {})
| .platforms["windows-x86_64"] = {"signature": $sig, "url": $url}
' release-files/latest.json > "$tmp"
mv "$tmp" release-files/latest.json
# merge_entry <platform_key> <msi_glob>
# Tauri's MSI filename embeds the architecture: "Lap_<version>_x64_en-US.msi"
# or "Lap_<version>_arm64_en-US.msi", so we can separate architectures by glob.
merge_entry() {
local key="$1"
local glob="$2"
local msi
msi="$(find release-files -maxdepth 1 -type f -name "$glob" ! -name '*.sig' | head -n 1)"
if [ -z "${msi}" ]; then
echo "No MSI found matching '$glob' for $key — skipping."
return 0
fi
local sig_file="${msi}.sig"
if [ ! -f "$sig_file" ]; then
echo "Missing updater signature file for $msi ($key)."
exit 1
fi
local name sig_content tmp
name="$(basename "$msi")"
sig_content="$(cat "$sig_file")"
tmp="$(mktemp)"
jq \
--arg version "$VERSION" \
--arg pub_date "$PUB_DATE" \
--arg key "$key" \
--arg sig "$sig_content" \
--arg url "https://github.com/${REPO}/releases/download/${TAG}/${name}" \
'
.version = $version
| .pub_date = $pub_date
| .platforms = (.platforms // {})
| .platforms[$key] = {"signature": $sig, "url": $url}
' release-files/latest.json > "$tmp"
mv "$tmp" release-files/latest.json
echo "Recorded $key -> $name"
}
merge_entry "windows-x86_64" "*_x64_*.msi"
merge_entry "windows-aarch64" "*_arm64_*.msi"
echo "Final latest.json:"
cat release-files/latest.json
- name: Upload Windows assets to GitHub Release
env:
+44 -8
View File
@@ -1,3 +1,9 @@
[CmdletBinding()]
param(
[ValidateSet("x64", "x86_64", "arm64", "aarch64")]
[string]$Arch
)
$ErrorActionPreference = "Stop"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
@@ -7,25 +13,55 @@ if (-not (Test-Path $TargetDir)) {
New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null
}
if (-not $Arch) {
$procArch = $env:PROCESSOR_ARCHITECTURE
if ($procArch -eq "ARM64") {
$Arch = "arm64"
}
else {
$Arch = "x64"
}
Write-Host "No -Arch specified; auto-detected $Arch (PROCESSOR_ARCHITECTURE=$procArch)."
}
switch ($Arch) {
{ $_ -in "x64", "x86_64" } {
$TripleSuffix = "x86_64-pc-windows-msvc"
}
{ $_ -in "arm64", "aarch64" } {
$TripleSuffix = "aarch64-pc-windows-msvc"
}
default {
throw "Unsupported architecture: $Arch"
}
}
$ReleaseBase = "https://github.com/julyx10/lap-binaries/releases/download/ffmpeg-8.1"
$Downloads = @(
"ffmpeg-x86_64-pc-windows-msvc.exe",
"ffprobe-x86_64-pc-windows-msvc.exe"
"ffmpeg-$TripleSuffix.exe",
"ffprobe-$TripleSuffix.exe"
)
Write-Host "Downloading FFmpeg sidecar files into $TargetDir..."
Write-Host "Downloading FFmpeg sidecar files ($Arch) into $TargetDir..."
foreach ($Filename in $Downloads) {
$Url = "$ReleaseBase/$Filename"
$Dest = Join-Path $TargetDir $Filename
if (Test-Path $Dest) {
Write-Host "✓ $Filename already exists, skipping."
Write-Host "# $Filename already exists, skipping."
continue
}
Write-Host "⬇ Downloading $Filename..."
Invoke-WebRequest -Uri $Url -OutFile $Dest -UseBasicParsing
Write-Host "✓ $Filename downloaded."
Write-Host "# Downloading $Filename..."
try {
Invoke-WebRequest -Uri $Url -OutFile $Dest -UseBasicParsing
}
catch {
Write-Error "Failed to download $Url. If this is an arm64 build and the binary has not been published yet, upload ffmpeg-aarch64-pc-windows-msvc.exe and ffprobe-aarch64-pc-windows-msvc.exe to the julyx10/lap-binaries release tag 'ffmpeg-8.1', or temporarily use the x64 binaries via Windows 11 ARM64 emulation."
throw
}
Write-Host "# $Filename downloaded."
}
Write-Host "All FFmpeg sidecar files downloaded into $TargetDir."
Write-Host "All FFmpeg sidecar files downloaded into $TargetDir."
+39 -195
View File
@@ -11,6 +11,7 @@ dependencies = [
"blake3",
"cc",
"chrono",
"csv",
"dirs 5.0.1",
"fast_image_resize",
"http",
@@ -26,7 +27,7 @@ dependencies = [
"ort",
"pinyin",
"rand 0.8.5",
"reverse_geocoder",
"rstar",
"rusqlite",
"serde",
"serde_json",
@@ -261,12 +262,6 @@ dependencies = [
"arrayvec",
]
[[package]]
name = "az"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7"
[[package]]
name = "base64"
version = "0.13.1"
@@ -1082,12 +1077,6 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "divrem"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69dde51e8fef5e12c1d65e0929b03d66e4c0c18282bc30ed2ca050ad6f44dd82"
[[package]]
name = "dlopen2"
version = "0.8.2"
@@ -1111,12 +1100,6 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "doc-comment"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9"
[[package]]
name = "document-features"
version = "0.2.12"
@@ -1183,12 +1166,6 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "elapsed"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f4e5af126dafd0741c2ad62d47f68b28602550102e5f0dd45c8a97fc8b49c29"
[[package]]
name = "embed-resource"
version = "3.0.8"
@@ -1378,19 +1355,6 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "fixed"
version = "1.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9af2cbf772fa6d1c11358f92ef554cb6b386201210bcf0e91fb7fba8a907fb40"
dependencies = [
"az",
"bytemuck",
"half",
"num-traits",
"typenum",
]
[[package]]
name = "flate2"
version = "1.1.9"
@@ -1676,21 +1640,6 @@ dependencies = [
"x11",
]
[[package]]
name = "generator"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9"
dependencies = [
"cc",
"cfg-if",
"libc",
"log",
"rustversion",
"windows-link 0.2.1",
"windows-result 0.4.1",
]
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -1946,6 +1895,15 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "hash32"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
dependencies = [
"byteorder",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
@@ -1985,6 +1943,16 @@ dependencies = [
"hashbrown 0.14.5",
]
[[package]]
name = "heapless"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
dependencies = [
"hash32",
"stable_deref_trait",
]
[[package]]
name = "heck"
version = "0.4.1"
@@ -2375,12 +2343,6 @@ dependencies = [
"cfb",
]
[[package]]
name = "init_with"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0175f63815ce00183bf755155ad0cb48c65226c5d17a724e369c25418d2b7699"
[[package]]
name = "interpolate_name"
version = "0.2.4"
@@ -2445,15 +2407,6 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.14.0"
@@ -2780,29 +2733,6 @@ dependencies = [
"unicode-segmentation",
]
[[package]]
name = "kiddo"
version = "4.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60c5fcd3044b774e2c80a502b2387b75d1baa95e99b2bceeb5db00f2e2d27fe9"
dependencies = [
"az",
"divrem",
"doc-comment",
"elapsed",
"fixed",
"generator",
"init_with",
"itertools 0.13.0",
"log",
"num-traits",
"ordered-float",
"sorted-vec",
"tracing",
"tracing-subscriber",
"ubyte",
]
[[package]]
name = "kuchikiki"
version = "0.8.8-speedreader"
@@ -2893,6 +2823,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "libm"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]]
name = "libredox"
version = "0.1.15"
@@ -3298,15 +3234,6 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
@@ -3370,6 +3297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"libm",
]
[[package]]
@@ -3714,15 +3642,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "ordered-float"
version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951"
dependencies = [
"num-traits",
]
[[package]]
name = "ort"
version = "2.0.0-rc.10"
@@ -4698,18 +4617,6 @@ dependencies = [
"web-sys",
]
[[package]]
name = "reverse_geocoder"
version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c987d5006fe57c099370a219602d52da978376fa7bf3324e036ad647beafda2"
dependencies = [
"csv",
"kiddo",
"serde",
"serde_derive",
]
[[package]]
name = "rfd"
version = "0.16.0"
@@ -4754,6 +4661,17 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "rstar"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb"
dependencies = [
"heapless",
"num-traits",
"smallvec 1.15.1",
]
[[package]]
name = "rusqlite"
version = "0.32.1"
@@ -5216,15 +5134,6 @@ dependencies = [
"digest",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shared_child"
version = "1.1.1"
@@ -5361,12 +5270,6 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "sorted-vec"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19f58d7b0190c7f12df7e8be6b79767a0836059159811b869d5ab55721fe14d0"
[[package]]
name = "soup3"
version = "0.5.0"
@@ -6097,15 +6000,6 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]]
name = "tiff"
version = "0.11.3"
@@ -6410,21 +6304,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "tracing-core"
version = "0.1.36"
@@ -6432,32 +6314,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec 1.15.1",
"thread_local",
"tracing-core",
"tracing-log",
]
[[package]]
@@ -6516,12 +6372,6 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "ubyte"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea"
[[package]]
name = "unic-char-property"
version = "0.9.0"
@@ -6698,12 +6548,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "vcpkg"
version = "0.2.15"
+3 -2
View File
@@ -41,7 +41,8 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
rusqlite = { version = "0.32.1", features = ["bundled", "collation"] }
chrono = "0.4"
reverse_geocoder = "4.1.1"
rstar = "0.12"
csv = "1"
dirs = "5.0.1"
walkdir = "2.5.0"
trash = "3.3.1"
@@ -75,4 +76,4 @@ libc = "0.2"
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
default = ["custom-protocol"]
custom-protocol = ["tauri/custom-protocol"]
devtools = ["tauri/devtools"]
devtools = ["tauri/devtools"]
File diff suppressed because it is too large Load Diff
+81 -1
View File
@@ -9,7 +9,7 @@ use crate::t_sqlite::{AFile, Album};
use chrono::{DateTime, Local, TimeZone, Utc};
use once_cell::sync::Lazy;
use pinyin::ToPinyin;
use reverse_geocoder::ReverseGeocoder;
use rstar::{AABB, PointDistance, RTree, RTreeObject};
use std::collections::HashMap;
use std::fs;
use std::io::Read;
@@ -29,6 +29,86 @@ use walkdir::WalkDir; // https://docs.rs/walkdir/2.5.0/walkdir/
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
// reverse geocoder
#[derive(serde::Deserialize)]
pub struct GeoRecord {
pub lat: f64,
pub lon: f64,
pub name: String,
pub admin1: String,
pub admin2: String,
pub cc: String,
}
struct CityPoint {
xyz: [f64; 3],
idx: u32,
}
impl RTreeObject for CityPoint {
type Envelope = AABB<[f64; 3]>;
fn envelope(&self) -> Self::Envelope {
AABB::from_point(self.xyz)
}
}
impl PointDistance for CityPoint {
fn distance_2(&self, point: &[f64; 3]) -> f64 {
let dx = self.xyz[0] - point[0];
let dy = self.xyz[1] - point[1];
let dz = self.xyz[2] - point[2];
dx * dx + dy * dy + dz * dz
}
}
fn lat_lon_to_xyz(lat: f64, lon: f64) -> [f64; 3] {
let lat = lat.to_radians();
let lon = lon.to_radians();
[lat.cos() * lon.cos(), lat.cos() * lon.sin(), lat.sin()]
}
pub struct ReverseGeocoder {
records: Vec<GeoRecord>,
tree: RTree<CityPoint>,
}
pub struct SearchResult<'a> {
pub record: &'a GeoRecord,
}
impl ReverseGeocoder {
pub fn new() -> ReverseGeocoder {
let cities = include_str!("../data/cities.csv");
let mut reader = csv::ReaderBuilder::new()
.has_headers(true)
.from_reader(cities.as_bytes());
let mut records: Vec<GeoRecord> = Vec::with_capacity(150_000);
let mut points: Vec<CityPoint> = Vec::with_capacity(150_000);
for row in reader.deserialize() {
let r: GeoRecord = row.expect("malformed cities.csv row");
points.push(CityPoint {
xyz: lat_lon_to_xyz(r.lat, r.lon),
idx: records.len() as u32,
});
records.push(r);
}
ReverseGeocoder {
records,
tree: RTree::bulk_load(points),
}
}
pub fn search(&self, loc: (f64, f64)) -> SearchResult<'_> {
let query = lat_lon_to_xyz(loc.0, loc.1);
let nearest = self
.tree
.nearest_neighbor(&query)
.expect("cities tree is empty");
SearchResult {
record: &self.records[nearest.idx as usize],
}
}
}
pub static GEOCODER: Lazy<ReverseGeocoder> = Lazy::new(|| {
println!("Initializing ReverseGeocoder...");
ReverseGeocoder::new()
+10 -2
View File
@@ -98,10 +98,14 @@ fn ffmpeg_sidecar_name() -> &'static str {
{
"ffmpeg-aarch64-unknown-linux-gnu"
}
#[cfg(target_os = "windows")]
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
{
"ffmpeg-x86_64-pc-windows-msvc.exe"
}
#[cfg(all(target_os = "windows", target_arch = "aarch64"))]
{
"ffmpeg-aarch64-pc-windows-msvc.exe"
}
}
fn ffprobe_sidecar_name() -> &'static str {
@@ -121,10 +125,14 @@ fn ffprobe_sidecar_name() -> &'static str {
{
"ffprobe-aarch64-unknown-linux-gnu"
}
#[cfg(target_os = "windows")]
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
{
"ffprobe-x86_64-pc-windows-msvc.exe"
}
#[cfg(all(target_os = "windows", target_arch = "aarch64"))]
{
"ffprobe-aarch64-pc-windows-msvc.exe"
}
}
fn find_sidecar(name: &str) -> Option<PathBuf> {