Skip to content

fix: 修复导出铺面时的诸多问题#38

Open
Symb0x76 wants to merge 2 commits intoMuNET-OSS:mainfrom
Symb0x76:main
Open

fix: 修复导出铺面时的诸多问题#38
Symb0x76 wants to merge 2 commits intoMuNET-OSS:mainfrom
Symb0x76:main

Conversation

@Symb0x76
Copy link

问题与解决办法

1. 音频解析失败(cueId 与 musicId 不一致)

  • 现象: 部分曲目导出失败,日志显示找不到 ACB/AWB 或音频解析异常。

  • 根因: 有些曲目使用 cueId 指向其他音频资源,旧逻辑仅按 musicId 查找。

  • 解决办法

  1. 导出时优先按 cueId 解析音频,再回退 musicId/nonDxId
  2. 解析失败时给出明确错误,不再静默失败。

2. 带 BGA 导出崩溃(Python Runtime 访问冲突)

  • 现象: 导出到某些曲目时直接崩溃,日志常见 Fatal error 0xC0000005,堆栈落在 Python.Runtime

  • 根因: 主进程内反复 PythonEngine.Initialize/Shutdown 在高频场景下不稳定。

  • 解决办法

  1. 将 WannaCRI 调用改为子进程隔离执行。
  2. 即便 Python 子进程异常,也不会直接带崩主进程。
  3. pv.mp4 转换失败时降级为"跳过视频并记录 warning/失败日志",不中断。

3. 批量导出 Name is not allowed

  • 现象
  1. 提示 Failed to execute 'getDirectoryHandle' ... Name is not allowed
  2. 常见在含特殊符号/全角符号曲名(例如 相关曲目)时触发。
  • 根因
  1. 路径片段净化不足,存在 File System API 不接受的名称组合。
  2. 仅入口处净化不够,写入路径阶段仍可能带入非法段名。
  • 解决办法
  1. remoteExport.ts 在生成目录名时净化。

  2. getSubDirFile.ts 在实际写入前再次逐段净化兜底。

  3. 非法字符改为全角映射(不是简单下划线),保留歌名可读性:

    • / ->
    • \\ ->
    • : ->
    • * ->
    • ? ->
    • " ->
    • < ->
    • > ->
    • | ->
  4. Unicode 归一化由 NFKC 调整为 NFC,保留全角标点样式(例如 )。

4. 导出目录重名冲突

  • 现象: 同名曲或规范化后同名会互相覆盖。

  • 根因: 目录名未做唯一化。

  • 解决办法: 构建唯一目录映射,重名自动追加 (2)/(3)

Copilot AI review requested due to automatic review settings February 15, 2026 13:28
@gemini-code-assist
Copy link

Summary of Changes

Hello @Symb0x76, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求旨在显著提升音乐导出功能的稳定性和用户体验。它通过解决音频文件解析逻辑的缺陷、优化外部 Python 进程调用的健壮性、增强文件系统路径名称的净化处理,以及引入导出目录的唯一性管理,全面提升了导出操作的成功率和可靠性,尤其是在处理包含特殊字符或复杂媒体资源的曲目时。

Highlights

  • 音频解析失败 (cueId 与 musicId 不一致): 修复了部分曲目因 cueId 与 musicId 不一致导致音频文件无法正确解析的问题,现在优先使用 cueId,并提供明确的错误提示。
  • 带 BGA 导出崩溃 (Python Runtime 访问冲突): 解决了导出带 BGA (背景动画) 曲目时因 Python.Runtime 频繁初始化/关闭导致程序崩溃的问题,现在将 WannaCRI 调用隔离到子进程执行,并优化了视频转换失败时的处理,避免中断导出。
  • 批量导出 "Name is not allowed": 解决了批量导出时因曲目名称包含特殊字符或全角符号导致文件系统 API 报错的问题,通过在前端和后端进行路径片段净化,并将非法字符映射为全角字符,同时调整 Unicode 归一化方式以保留全角标点样式。
  • 导出目录重名冲突: 解决了同名曲目或规范化后同名曲目导出时互相覆盖的问题,现在会自动为重名目录追加 (2)/(3) 等后缀以确保唯一性。
Changelog
  • .gitignore
    • 添加了 *.code-workspace 到忽略列表。
  • MaiChartManager/Controllers/Music/MusicTransferController.cs
    • 引入了 MaiChartManager.Models 命名空间。
    • 新增了 GetAudioCandidateIds 和 BuildAudioResolveErrorMessage 辅助方法,用于处理音频 ID 候选列表和生成错误信息。
    • 在音乐文件复制前增加了源目录有效性检查,避免因路径问题导致导出失败。
    • 更新了 ACB/AWB 音频文件的复制逻辑,现在会尝试解析多个音频 ID 候选,并在解析失败时记录警告。
    • 修改了 ExportOpt 和 ExportAsMaidata 方法,以使用新的音频解析逻辑和目录检查。
    • 改进了 ExportAsMaidata 中视频导出的健壮性,增加了异常捕获和临时目录清理,确保视频转换失败时不会中断整个导出过程。
    • 在 ModifyId 方法中添加了对音乐文件源目录的有效性检查。
  • MaiChartManager/Front/src/components/MusicList/BatchActionButton/remoteExport.ts
    • 导入了 sanitizeFsSegment 工具函数。
    • 实现了目录名唯一化逻辑,包括 usedDirNamesByParent、exportDirByMusic 和 getUniqueDirName,以避免导出目录重名。
    • 在生成导出路径时应用了文件系统段净化和唯一化逻辑。
    • 增强了网络请求和 Zip 文件处理的错误处理机制,为用户提供更明确的失败通知。
  • MaiChartManager/Front/src/utils/getSubDirFile.ts
    • 导入了 sanitizeFsSegment 工具函数。
    • 修改了路径分割和处理逻辑,对每个路径片段进行净化,并增加了对空路径的检查。
  • MaiChartManager/Front/src/utils/sanitizeFsName.ts
    • 新增文件: 定义了 ILLEGAL_FS_CHAR_MAP,用于将非法文件系统字符映射为全角字符。
    • 新增文件: 实现了 sanitizeRawSegment 函数,用于对字符串进行 Unicode NFC 归一化、非法字符替换和空白字符清理。
    • 新增文件: 导出了 sanitizeFsSegment 函数,提供一个健壮的文件系统段名称净化方法,并支持指定备用名称。
  • MaiChartManager/Program.cs
    • 为 MaiChartManager.WannaCRI.WannaCRI 添加了 WannaCriRunner 别名。
    • 修改了 Main 方法,使其能够通过命令行参数作为 WannaCRI 的辅助进程运行,从而实现进程隔离。
  • MaiChartManager/Utils/AudioConvert.cs
    • 新增了 GetDistinctAudioIds 辅助方法,用于从多个 ID 中提取唯一的音频 ID。
    • 实现了 TryResolveAcbAwb 方法,用于根据给定的音乐 ID 候选列表尝试解析并返回 ACB/AWB 文件的路径。
    • 更新了 GetCachedWavPath 方法,使其能够接受多个音乐 ID 候选,并利用 TryResolveAcbAwb 进行音频文件查找。
    • 新增了一个 GetCachedWavPath 的重载,直接接受 ACB 和 AWB 文件路径。
  • MaiChartManager/WannaCRI/WannaCRI.cs
    • 将 RunWannaCRIWithArgs 重命名为 RunWannaCRIWithArgsInCurrentProcess。
    • 新增了 RunWannaCRIWithArgsInHelperProcess 方法,用于在独立的子进程中执行 WannaCRI 命令,以提高稳定性。
    • 新增了 RunHelper 方法,作为 WannaCRI 辅助进程的入口点,处理命令行参数并执行相应的 WannaCRI 逻辑。
    • 更新了 CreateUsm 和 UnpackUsm 方法,使其现在通过 RunWannaCRIWithArgsInHelperProcess 调用 WannaCRI。
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/build.yml
Activity
  • 目前没有与此拉取请求相关的评论、审查或进展活动。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

此 PR 聚焦于提升谱面/maidata 导出稳定性与兼容性:修复音频资源解析在 cueIdmusicId 不一致时的失败问题;将 WannaCRI(Python.Runtime)调用隔离到子进程以避免主进程崩溃;并在前端导出时加强目录/文件名净化与重名处理,减少 File System Access API 写入失败。

Changes:

  • 音频解析:支持按候选 ID(cueId/id/nonDxId)解析 ACB/AWB,并在失败时输出更明确的错误。
  • 视频导出:WannaCRI 改为通过 helper 子进程执行,导出 pv.mp4 失败时降级跳过并记录 warning。
  • 前端批量导出:新增分段净化(全角映射 + NFC)与同名目录唯一化逻辑,避免 “Name is not allowed” 与覆盖冲突。

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
MaiChartManager/WannaCRI/WannaCRI.cs 新增 helper 子进程执行路径,避免 Python.Runtime 初始化/销毁导致崩溃
MaiChartManager/Program.cs 增加 --run-wannacri 分支作为 helper 入口
MaiChartManager/Utils/AudioConvert.cs 新增多候选音频解析与按 ACB/AWB 路径缓存 wav 的能力
MaiChartManager/Controllers/Music/MusicTransferController.cs 导出/打包时按候选 ID 解析音频;视频导出失败降级;加强源目录校验与错误信息
MaiChartManager/Front/src/utils/sanitizeFsName.ts 新增路径段净化工具(全角映射 + NFC + 去尾点/空白/控制字符)
MaiChartManager/Front/src/utils/getSubDirFile.ts 写入前对每个路径段进行净化兜底,避免非法段名
MaiChartManager/Front/src/components/MusicList/BatchActionButton/remoteExport.ts 生成安全且唯一的导出目录名;增强 fetch/zip 读取错误处理
.gitignore 忽略 *.code-workspace
.github/workflows/build.yml YAML 格式/缩进调整(功能不变)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses multiple critical issues in the export function, including audio parsing, BGA export crashes, and handling of illegal filenames and directory conflicts. A key architectural improvement is the isolation of WannaCRI Python calls into a subprocess, significantly enhancing stability and robustness. However, a high-severity path traversal vulnerability has been identified in the new filename sanitization logic within getSubDirFile.ts, which could allow directory traversal attacks using .. due to improper path segment sanitization. Additionally, the PR improves frontend handling of file and directory names for better compatibility and prevents overwriting of existing directories.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant