Skip to content

Commit f7a3a88

Browse files
authored
fix: 多线程并行导出谱面的相关问题 (#55)
* fix: missing new MuNET-UI in vcs.xml * fix: 多线程批量导出谱面时,并发未加锁调用ACB_Load引起的问题 * fix: 批量导出谱面时,wav文件生成后不会被自动删除造成内存爆炸的问题 我批量导出1000多个谱面,导出到一半,C:\Users\username\AppData\Local\Temp\MaiChartManager就占用了近20G磁盘,把我C盘吃满导出失败了。 * 给ConvertToMai里的ACB_File.Load也加上锁 * [F] 导出时改为使用Audio.AcbToWav实时在内存中创建WAV,同时修改ConvertWavPathToMp3Stream为直接接受wav的字节。
1 parent a3128b3 commit f7a3a88

4 files changed

Lines changed: 24 additions & 10 deletions

File tree

.idea/.idea.Sitreamai/.idea/vcs.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MaiChartManager/Controllers/Music/MusicTransferController.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -656,15 +656,15 @@ public async Task ExportAsMaidata(int id, string assetDir, bool ignoreVideo = fa
656656
Comment = version?.GenreName,
657657
AlbumArt = img,
658658
};
659-
var wavPath = await AudioConvert.GetCachedWavPath(GetAudioCandidateIds(music));
660-
if (wavPath is null)
659+
660+
if (!AudioConvert.TryResolveAcbAwb(GetAudioCandidateIds(music), out _, out var acbPath, out var awbPath) || acbPath is null || awbPath is null)
661661
{
662662
var message = BuildAudioResolveErrorMessage(music);
663663
logger.LogError("{message}", message);
664664
throw new FileNotFoundException(message);
665665
}
666-
667-
AudioConvert.ConvertWavPathToMp3Stream(wavPath, soundStream, tag);
666+
var wav = Audio.AcbToWav(acbPath);
667+
AudioConvert.ConvertWavToMp3Stream(wav, soundStream, tag);
668668
soundStream.Close();
669669

670670
if (!ignoreVideo && StaticSettings.MovieDataMap.TryGetValue(music.NonDxId, out var movieUsmPath))

MaiChartManager/Utils/Audio.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ public static class Audio
1111
{
1212
public static void ConvertToMai(string srcPath, string savePath, float padding = 0, Stream? src = null, string? previewFilename = null, Stream? preview = null, bool forceUseNAudio = false)
1313
{
14-
var wrapper = new ACB_Wrapper(ACB_File.Load(File.ReadAllBytes(Path.Combine(StaticSettings.exeDir, previewFilename is null ? "nopreview.acb" : "template.acb")), null));
14+
ACB_File acbTemplate;
15+
lock (_acbFileLoadLock) {
16+
acbTemplate = ACB_File.Load(File.ReadAllBytes(Path.Combine(StaticSettings.exeDir, previewFilename is null ? "nopreview.acb" : "template.acb")), null);
17+
}
18+
var wrapper = new ACB_Wrapper(acbTemplate);
1519
var trackBytes = LoadAndConvertFile(srcPath, FileType.Hca, false, 9170825592834449000, padding, src, forceUseNAudio);
1620

1721
wrapper.Cues[0].AddTrackToCue(trackBytes, true, false, EncodeType.HCA);
@@ -172,10 +176,15 @@ private static FileType GetFileType(EncodeType encodeType)
172176
return FileType.NotSet;
173177
}
174178
}
179+
180+
private static readonly object _acbFileLoadLock = new();
175181

176182
public static byte[] AcbToWav(string acbPath)
177183
{
178-
var acb = ACB_File.Load(acbPath);
184+
ACB_File acb;
185+
lock (_acbFileLoadLock) {
186+
acb = ACB_File.Load(acbPath);
187+
}
179188
var wave = acb.GetWaveformsFromCue(acb.Cues[0])[0];
180189
var entry = acb.GetAfs2Entry(wave.AwbId);
181190
using MemoryStream stream = new MemoryStream(entry.bytes);

MaiChartManager/Utils/AudioConvert.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,26 @@ public static async Task<string> GetCachedWavPath(string acbPath, string awbPath
7373
return cachePath;
7474
}
7575

76-
public static void ConvertWavPathToMp3Stream(string wavPath, Stream mp3Stream, ID3TagData? tagData = null)
76+
public static void ConvertWavToMp3Stream(byte[] wav, Stream mp3Stream, ID3TagData? tagData = null)
7777
{
78-
var outputPath = Path.Combine(StaticSettings.tempPath, $"ConvertToMp3_{Guid.NewGuid():N}.mp3");
78+
var tempFileGuid = Guid.NewGuid();
79+
var inputPath = Path.Combine(StaticSettings.tempPath, $"ConvertToMp3_{tempFileGuid:N}.wav");
80+
var outputPath = Path.Combine(StaticSettings.tempPath, $"ConvertToMp3_{tempFileGuid:N}.mp3");
7981
string? albumArtPath = null;
8082
try
8183
{
8284
Directory.CreateDirectory(StaticSettings.tempPath);
85+
File.WriteAllBytes(inputPath, wav);
8386

8487
var conversion = FFmpeg.Conversions.New()
85-
.AddParameter($"-i " + FFmpegHelper.Escape(wavPath));
88+
.AddParameter($"-i " + FFmpegHelper.Escape(inputPath));
8689

8790
if (tagData != null)
8891
{
8992
if (tagData.AlbumArt != null && tagData.AlbumArt.Length > 0)
9093
{
9194
// 把专辑封面写到临时文件,然后让ffmpeg把它嵌入mp3
92-
albumArtPath = Path.Combine(StaticSettings.tempPath, $"ConvertToMp3_{Guid.NewGuid():N}.png");
95+
albumArtPath = Path.Combine(StaticSettings.tempPath, $"ConvertToMp3_{tempFileGuid:N}.png");
9396
File.WriteAllBytes(albumArtPath, tagData.AlbumArt);
9497
conversion.AddParameter($"-i {FFmpegHelper.Escape(albumArtPath)}");
9598
} // 顺序不能换!这个必须在第一个,因为-i必须在任何其他参数之前。
@@ -122,6 +125,7 @@ public static void ConvertWavPathToMp3Stream(string wavPath, Stream mp3Stream, I
122125
}
123126
finally
124127
{
128+
File.Delete(inputPath);
125129
File.Delete(outputPath);
126130
if (albumArtPath != null) File.Delete(albumArtPath);
127131
}

0 commit comments

Comments
 (0)