From 75a9d3c6414da795907899ed856e99646c54c6d9 Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 00:15:58 +0800 Subject: [PATCH 1/9] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20macOS=20?= =?UTF-8?q?=E8=A7=A3=E9=94=81=E5=B8=A7=E7=8E=87=E6=8F=92=E4=BB=B6=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/player/src-tauri/tauri.conf.json | 1 - packages/player/src-tauri/tauri.macos.conf.json | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 packages/player/src-tauri/tauri.macos.conf.json diff --git a/packages/player/src-tauri/tauri.conf.json b/packages/player/src-tauri/tauri.conf.json index 93a09542..8a31fddd 100644 --- a/packages/player/src-tauri/tauri.conf.json +++ b/packages/player/src-tauri/tauri.conf.json @@ -32,7 +32,6 @@ "version": "0.0.1", "identifier": "net.stevexmh.amllplayer", "plugins": { - "macos-fps": {}, "updater": { "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDVBMzY2M0I2Qjc4MjBBNTUKUldSVkNvSzN0bU0yV2k0bUhxcm9jczBNYk9lTllYaTFyWHVEZ2xaSloxaVhpSnQ1RHZFSUtnS2IK", "endpoints": [ diff --git a/packages/player/src-tauri/tauri.macos.conf.json b/packages/player/src-tauri/tauri.macos.conf.json new file mode 100644 index 00000000..26cdf2f3 --- /dev/null +++ b/packages/player/src-tauri/tauri.macos.conf.json @@ -0,0 +1,5 @@ +{ + "plugins": { + "macos-fps": {} + } +} From 6034e40e406069469c1ebff09564efc1997559dc Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 00:23:27 +0800 Subject: [PATCH 2/9] =?UTF-8?q?build(ios):=20=E9=85=8D=E7=BD=AE=20iOS=20?= =?UTF-8?q?=E7=9B=AE=E6=A0=87=E7=9A=84=20FFmpeg=20=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cargo/config.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..4472b0bb --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[env] +FFMPEG_DIR_AARCH64_APPLE_IOS = { value = "vendor/ffmpeg_ios", relative = true } +FFMPEG_DIR_aarch64_apple_ios = { value = "vendor/ffmpeg_ios", relative = true } From 979abbf06b1703675800bb3016e507e62e3085d2 Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 00:30:07 +0800 Subject: [PATCH 3/9] =?UTF-8?q?build(ios):=20=E5=BC=95=E5=85=A5=20iOS=20?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E6=89=80=E9=9C=80=E7=9A=84=20objc2=20?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/player/src-tauri/Cargo.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/player/src-tauri/Cargo.toml b/packages/player/src-tauri/Cargo.toml index 9a71b886..8fe284be 100644 --- a/packages/player/src-tauri/Cargo.toml +++ b/packages/player/src-tauri/Cargo.toml @@ -75,6 +75,11 @@ objc2 = "^0.6" objc2-avf-audio = "^0.3" tauri-plugin-macos-fps = "0.1.0" +[target.'cfg(target_os = "ios")'.dependencies] +objc2 = "^0.6" +objc2-avf-audio = "^0.3" +objc2-foundation = "^0.3" + [target.'cfg(target_os = "windows")'.dependencies] webview2-com = "0.38" taskbar-lyric = { git = "https://github.com/apoint123/taskbar-lyric.git", features = [ From 37895450b6314af08a9b8462c6f7113b359c2d25 Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 00:34:47 +0800 Subject: [PATCH 4/9] =?UTF-8?q?feat(ios):=20=E5=88=9D=E5=A7=8B=E5=8C=96=20?= =?UTF-8?q?AVAudioSession=20=EF=BC=8C=E6=94=AF=E6=8C=81=20iOS=20=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E6=92=AD=E6=94=BE=E4=B8=8E=E9=9D=99=E9=9F=B3=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E6=92=AD=E6=94=BE=E9=9F=B3=E9=A2=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/player/src-tauri/src/lib.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/player/src-tauri/src/lib.rs b/packages/player/src-tauri/src/lib.rs index a29ce3d3..0b068435 100644 --- a/packages/player/src-tauri/src/lib.rs +++ b/packages/player/src-tauri/src/lib.rs @@ -527,6 +527,23 @@ pub fn run() { theme_watcher::get_system_theme ]) .setup(|app| { + #[cfg(target_os = "ios")] + { + use objc2::msg_send; + use objc2_avf_audio::AVAudioSession; + use objc2_foundation::ns_string; + + info!("Initializing iOS AVAudioSession Category to Playback..."); + unsafe { + let session = AVAudioSession::sharedInstance(); + let category = ns_string!("AVAudioSessionCategoryPlayback"); + + let _: () = msg_send![&session, setCategory: category, error: std::ptr::null_mut::<*mut *mut objc2_foundation::NSError>()]; + + let _: bool = msg_send![&session, setActive: true, error: std::ptr::null_mut::<*mut *mut objc2_foundation::NSError>()]; + } + info!("iOS AVAudioSession Category set to Playback successfully!"); + } #[cfg(target_os = "android")] { if let Some(webview) = app.get_webview_window("main") { From 01f1c17c8b5569ce61200f7cca14dfd14019ecd2 Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 00:37:58 +0800 Subject: [PATCH 5/9] =?UTF-8?q?chore(scripts):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=E7=94=9F=E6=88=90=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E9=80=82=E9=85=8D=20iOS=20=E6=89=93=E5=8C=85=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/player/scripts/gen-dev-version.mjs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/player/scripts/gen-dev-version.mjs b/packages/player/scripts/gen-dev-version.mjs index eeb5b3fc..3eee0ce4 100644 --- a/packages/player/scripts/gen-dev-version.mjs +++ b/packages/player/scripts/gen-dev-version.mjs @@ -29,10 +29,20 @@ if (!/^[0-9]+\.[0-9]+\.[0-9]+$/.test(baseVersion)) { // const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim(); const commitCount = execSync("git rev-list --count HEAD").toString().trim(); -const devVersion = `${baseVersion}+${commitCount}`; - -tauriConf.version = devVersion; - -console.log(`Generated dev version: ${baseVersion} -> ${devVersion}`); +const isIos = process.env.AMLL_IOS_BUILD === "true"; + +if (isIos) { + // iOS:版本号严格保持 3 位,构建号单独写入 bundle.iOS.bundleVersion + tauriConf.version = baseVersion; + if (!tauriConf.bundle) tauriConf.bundle = {}; + if (!tauriConf.bundle.iOS) tauriConf.bundle.iOS = {}; + tauriConf.bundle.iOS.bundleVersion = commitCount; + console.log(`Generated iOS dev version: ${baseVersion} (${commitCount})`); +} else { + // 其它平台:保留原有逻辑 + const devVersion = `${baseVersion}+${commitCount}`; + tauriConf.version = devVersion; + console.log(`Generated dev version: ${baseVersion} -> ${devVersion}`); +} writeFileSync(tauriConfPath, JSON.stringify(tauriConf, null, "\t")); From 9db0d73302c0b16a1acab9ae55f7018f0f74dce3 Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 00:43:57 +0800 Subject: [PATCH 6/9] =?UTF-8?q?ci:=20=E5=A2=9E=E5=8A=A0=20iOS=20=E6=97=A0?= =?UTF-8?q?=E7=AD=BE=E5=90=8D=20ipa=20=E6=9E=84=E5=BB=BA=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-player.yaml | 182 ++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/.github/workflows/build-player.yaml b/.github/workflows/build-player.yaml index 95475608..37ec0010 100644 --- a/.github/workflows/build-player.yaml +++ b/.github/workflows/build-player.yaml @@ -350,3 +350,185 @@ jobs: path: | packages/player/src-tauri/gen/android/app/build/outputs/**/*.apk packages/player/src-tauri/gen/android/app/build/outputs/**/*.aab + + build-tauri-ios: + name: 自动构建 iOS 移动版 (无签名 IPA) + needs: clean-pre-release + runs-on: macos-14 + + steps: + - uses: actions/checkout@v4 + name: 克隆仓库 + with: + fetch-depth: 0 + + - name: 选择 Xcode 16 版本 + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '16' + + - name: 安装 PNPM + uses: pnpm/action-setup@v4 + + - name: 安装 Node.js + uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: pnpm + + - name: 安装 Rust 工具链与 iOS 构建目标 + uses: dtolnay/rust-toolchain@v1 + with: + toolchain: stable + targets: "aarch64-apple-ios" + + - name: 配置 Rust 缓存 + uses: Swatinem/rust-cache@v2 + with: + workspaces: | + . -> target + packages/player/src-tauri -> target + key: ios-aarch64-only + + - name: 自动拉取并链接 iOS 预编译 FFmpeg 静态库 + shell: bash + env: + BUILDER_REPO: apoint123/ffmpeg-builder + FFMPEG_VERSION_TAG: "ffmpeg-8.0.1-cc5ef4262cfdcf5eba1e9d8b6d4020e9998c5680" + run: | + PACKAGE_NAME="ffmpeg-8.0.1-ios-arm64.tar.gz" + DOWNLOAD_URL="https://github.com/${BUILDER_REPO}/releases/download/${FFMPEG_VERSION_TAG}/${PACKAGE_NAME}" + EXTRACT_DIR="${{ github.workspace }}/vendor/ffmpeg_ios" + + echo "Downloading iOS FFmpeg static libraries from $DOWNLOAD_URL..." + curl -f -sL $DOWNLOAD_URL -o $PACKAGE_NAME + + mkdir -p $EXTRACT_DIR + echo "Extracting FFmpeg to $EXTRACT_DIR..." + tar -xzf $PACKAGE_NAME -C $EXTRACT_DIR + rm $PACKAGE_NAME + + # 设置链接编译所需的 FFMPEG_DIR 环境变量,映射真机目标 + echo "FFMPEG_DIR=$EXTRACT_DIR" >> $GITHUB_ENV + echo "FFMPEG_DIR_AARCH64_APPLE_IOS=$EXTRACT_DIR" >> $GITHUB_ENV + echo "FFMPEG_DIR_aarch64_apple_ios=$EXTRACT_DIR" >> $GITHUB_ENV + echo "FFmpeg iOS environment set up successfully." + + + - name: 安装 pnpm 依赖 + run: | + pnpm i --frozen-lockfile --ignore-scripts + env: + AMLL_GITHUB_IS_ACTION: true + + - name: 生成开发构建版本号 + run: | + node ./packages/player/scripts/gen-dev-version.mjs + env: + AMLL_IOS_BUILD: "true" + + - name: 自动初始化 iOS 工程并配置图标 + run: | + pnpm -F player tauri ios init + # 从高分辨率主图生成符合 iOS 规范的无切边专属图标集 + pnpm -F player tauri icon src-tauri/icons/512x512@2x.png + env: + AMLL_GITHUB_IS_ACTION: true + + - name: 禁用 Xcode 工程自动签名 (免证书构建) + shell: bash + run: | + # 修改自动签名配置为手动,强制关闭代码签名校验 + PBXPROJ="packages/player/src-tauri/gen/apple/amll-player.xcodeproj/project.pbxproj" + + node -e ' + const fs = require("fs"); + const path = process.argv[1]; + let content = fs.readFileSync(path, "utf8"); + + content = content.replace(/buildSettings = \{([\s\S]*?)\};/g, (match, body) => { + let newBody = body + .replace(/CODE_SIGN_STYLE = [^;]+;/g, "") + .replace(/DEVELOPMENT_TEAM = [^;]+;/g, "") + .replace(/CODE_SIGN_IDENTITY = [^;]+;/g, "") + .replace(/CODE_SIGNING_ALLOWED = [^;]+;/g, "") + .replace(/CODE_SIGNING_REQUIRED = [^;]+;/g, "") + .replace(/PROVISIONING_PROFILE_SPECIFIER = [^;]+;/g, "") + .split("\n") + .filter(line => line.trim() !== "") + .join("\n"); + + return `buildSettings = {\n${newBody}\n\t\t\t\tCODE_SIGNING_ALLOWED = NO;\n\t\t\t\tCODE_SIGNING_REQUIRED = NO;\n\t\t\t\tCODE_SIGN_IDENTITY = "";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tDEVELOPMENT_TEAM = "";\n\t\t\t};`; + }); + + fs.writeFileSync(path, content, "utf8"); + console.log("Successfully rewrote all buildSettings in project.pbxproj to disable signing."); + ' "$PBXPROJ" + + - name: 构建前端资源 + run: pnpm -F player build + env: + AMLL_GITHUB_IS_ACTION: true + + - name: 注入 iOS 后台音频播放权限 (Info.plist) + shell: bash + run: | + # 在 Xcode 工程生成后,通过 PlistBuddy 写入 UIBackgroundModes=audio 权限,支持后台切歌与播放 + PLIST_PATH="packages/player/src-tauri/gen/apple/amll-player_iOS/Info.plist" + /usr/libexec/PlistBuddy -c "Add :UIBackgroundModes array" "$PLIST_PATH" || true + /usr/libexec/PlistBuddy -c "Add :UIBackgroundModes:0 string audio" "$PLIST_PATH" || true + echo "Info.plist background audio modes injected." + + - name: 使用 Tauri CLI 构建无签名 iOS 应用 + shell: bash + run: | + # 使用 Tauri CLI 编译应用。无签名构建在导出归档时会提示报错(code 70), + # 若底层的 *.app 已经成功生成,我们捕获该状态并作为构建成功处理。 + pnpm -F player tauri ios build || { + echo "==== 已编译的 iOS 应用包 (.app) 路径列表 ====" + find packages/player/src-tauri/gen/apple -name "*.app" 2>/dev/null || true + find $HOME/Library/Developer/Xcode -name "*.app" 2>/dev/null || true + echo "==========================================" + + APP_PATH=$(find packages/player/src-tauri/gen/apple -name "*.app" 2>/dev/null | head -1) + if [ -z "$APP_PATH" ]; then + APP_PATH=$(find $HOME/Library/Developer/Xcode/DerivedData $HOME/Library/Developer/Xcode/Archives -name "*.app" 2>/dev/null | head -1) + fi + if [ -n "$APP_PATH" ] && [ -d "$APP_PATH" ]; then + echo "Tauri CLI exited with signing/export warning, but iOS app was compiled successfully!" + echo "Found compiled app at: $APP_PATH" + echo "Proceeding with manual unsigned packaging..." + else + echo "ERROR: Tauri CLI build failed and no compiled .app was found." + exit 1 + fi + } + env: + AMLL_GITHUB_IS_ACTION: true + SKIP_FRONTEND_BUILD: true + + - name: 压包并生成无签名版 .ipa + run: | + # 动态查找编译生成的 .app 目录并打包为无签名 .ipa 产物 + APP_PATH=$(find packages/player/src-tauri/gen/apple -name "*.app" 2>/dev/null | head -1) + if [ -z "$APP_PATH" ]; then + APP_PATH=$(find $HOME/Library/Developer/Xcode/DerivedData $HOME/Library/Developer/Xcode/Archives -name "*.app" 2>/dev/null | head -1) + fi + if [ -z "$APP_PATH" ]; then + echo "ERROR: Compiled .app not found. Listing possible locations:" + find . -name "*.app" 2>/dev/null + exit 1 + fi + echo "Found: $APP_PATH" + + mkdir -p build/Payload + cp -r "$APP_PATH" build/Payload/ + cd build && zip -r amll-player-unsigned.ipa Payload + echo "IPA created:" + ls -la amll-player-unsigned.ipa + + - name: 上传无签名 ipa 包至 GitHub Action Artifacts + uses: actions/upload-artifact@v4 + with: + name: AMLL Player iOS Unsigned IPA + path: build/amll-player-unsigned.ipa \ No newline at end of file From c472cb538eed778e8da30ac2aa49a654acaab36b Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 00:45:49 +0800 Subject: [PATCH 7/9] =?UTF-8?q?chore(ci):=20=E7=B2=BE=E7=AE=80=20Android?= =?UTF-8?q?=20=E4=B8=8E=20iOS=20=E6=9E=84=E5=BB=BA=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81=E9=83=A8=E5=88=86=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-player.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-player.yaml b/.github/workflows/build-player.yaml index 37ec0010..2871c9b5 100644 --- a/.github/workflows/build-player.yaml +++ b/.github/workflows/build-player.yaml @@ -335,7 +335,7 @@ jobs: run: | node ./packages/player/scripts/gen-dev-version.mjs - - name: 构建 AMLL Player 安卓移动版程序 + - name: 构建 AMLL Player 安卓版本 env: CARGO_NDK_ANDROID_PLATFORM: 26 run: | @@ -352,7 +352,7 @@ jobs: packages/player/src-tauri/gen/android/app/build/outputs/**/*.aab build-tauri-ios: - name: 自动构建 iOS 移动版 (无签名 IPA) + name: 构建 Tauri iOS 版本 needs: clean-pre-release runs-on: macos-14 @@ -390,7 +390,7 @@ jobs: packages/player/src-tauri -> target key: ios-aarch64-only - - name: 自动拉取并链接 iOS 预编译 FFmpeg 静态库 + - name: 拉取并链接 iOS 预编译 FFmpeg 静态库 shell: bash env: BUILDER_REPO: apoint123/ffmpeg-builder @@ -427,7 +427,7 @@ jobs: env: AMLL_IOS_BUILD: "true" - - name: 自动初始化 iOS 工程并配置图标 + - name: 初始化 iOS 工程并配置图标 run: | pnpm -F player tauri ios init # 从高分辨率主图生成符合 iOS 规范的无切边专属图标集 From 8b880d5e5312be104bf2d139ed8f10858768d7c1 Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 00:50:14 +0800 Subject: [PATCH 8/9] =?UTF-8?q?chore(ci):=20=E6=9B=B4=E6=AD=A3=20Android?= =?UTF-8?q?=20=E6=9E=84=E5=BB=BA=E5=B7=A5=E4=BD=9C=E6=B5=81=E5=90=8D?= =?UTF-8?q?=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-player.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-player.yaml b/.github/workflows/build-player.yaml index 2871c9b5..dda08e70 100644 --- a/.github/workflows/build-player.yaml +++ b/.github/workflows/build-player.yaml @@ -238,7 +238,7 @@ jobs: target/**/release/amll-player build-tauri-android: - name: 构建 Tauri 安卓移动版本 + name: 构建 Tauri 安卓版本 needs: clean-pre-release runs-on: ubuntu-latest @@ -531,4 +531,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: AMLL Player iOS Unsigned IPA - path: build/amll-player-unsigned.ipa \ No newline at end of file + path: build/amll-player-unsigned.ipa From 8516511f7bf5224dd1d854ef3ba07a4d1568f682 Mon Sep 17 00:00:00 2001 From: ITManCHINA <1678812512@qq.com> Date: Sun, 24 May 2026 01:12:32 +0800 Subject: [PATCH 9/9] =?UTF-8?q?chore(deps):=20iOS=20=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B9=B6=E6=9B=B4=E6=96=B0=20Cargo.lock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 201f2db4..6944f09b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,6 +93,7 @@ dependencies = [ "ndk-context", "objc2", "objc2-avf-audio", + "objc2-foundation", "reqwest 0.13.3", "rkyv", "rodio", @@ -1530,7 +1531,7 @@ dependencies = [ [[package]] name = "ffmpeg-sys-next" version = "8.1.0" -source = "git+https://github.com/apoint123/rust-ffmpeg-sys#65d35b3b7d34f20b37e310165a41548db12a4833" +source = "git+https://github.com/apoint123/rust-ffmpeg-sys#1c40a58859bd32b3e51acad2a6675b59d29d8a74" dependencies = [ "bindgen", "cc",