Skip to content

Instantly share code, notes, and snippets.

@Forenard
Created November 13, 2025 19:26
Show Gist options
  • Select an option

  • Save Forenard/cf7c397e5633b03a4d89a06a35c1b715 to your computer and use it in GitHub Desktop.

Select an option

Save Forenard/cf7c397e5633b03a4d89a06a35c1b715 to your computer and use it in GitHub Desktop.
brawlcrateの一括wav export plugin
# https://soopercool101.github.io/BrawlCrate/
# this shit is created by renard
__author__ = "Renard"
__version__ = "2.0.0"
SCRIPT_NAME = "Dump Music v2"
from BrawlCrate.API import BrawlAPI
from BrawlLib.SSBB.ResourceNodes import *
from BrawlCrate.NodeWrappers import *
from System.IO import Directory, Path as IOPath, File
from System import DateTime
# global
log_file = None
log_path = ""
def init_log(folder):
"""ログファイルを初期化"""
global log_file, log_path
log_path = IOPath.Combine(folder, "DumpMusic_Log_{0}.txt".format(
DateTime.Now.ToString("yyyyMMdd_HHmmss")))
try:
log_file = open(log_path, "w", encoding="utf-8")
except:
log_file = None
def append_log(message):
"""ログにリアルタイムで書き込む"""
global log_file
if log_file is not None:
try:
log_file.write(message)
log_file.flush() # 即座にディスクに書き込む
except:
pass
def close_log():
"""ログファイルを閉じる"""
global log_file
if log_file is not None:
try:
log_file.close()
except:
pass
log_file = None
def wav_search():
wrappers = BrawlAPI.NodeWrapperList
wav_list = []
for wrapper in wrappers:
append_log("Checking wrapper: {0}, ExportFilter: {1}\n".format(wrapper.Resource.Name, wrapper.ExportFilter))
if ".wav" in wrapper.ExportFilter:
wav_list += [wrapper.Resource]
return wav_list
def get_name(node):
"""再帰的にノード名を取得"""
names = []
current = node
while current is not None:
names.insert(0, current.Name)
current = current.Parent
return "_".join(names)
def sanitize_filename(name):
"""ファイル名として使えない文字を削除"""
invalid_chars = '<>:"/\\|?*'
for char in invalid_chars:
name = name.replace(char, '_')
return name.strip('. ')
def main():
if BrawlAPI.RootNode != None:
folder = BrawlAPI.OpenFolderDialog()
if folder:
# ログファイルを初期化
init_log(folder)
count = 0
failed = 0
wav_list = wav_search()
append_log("=== Dump Music Log ===\n")
append_log("Total nodes with WAV export filter: {0}\n\n".format(len(wav_list)))
for node in wav_list:
node_type = type(node).__name__
export_name = get_name(node)
# https://soopercool101.github.io/BrawlCrate/class_brawl_lib_1_1_s_s_b_b_1_1_resource_nodes_1_1_r_s_a_r_sound_node.html#a579038833dcd6c71c853d4d5512e5216
if node_type == 'RSARSoundNode':
try:
sound_type = int(node.SoundType)
except:
sound_type = -1
can_export = sound_type == 3 # WAVE
if not can_export:
continue
# エクスポート実行
try:
safe_name = sanitize_filename(export_name)
export_path = IOPath.Combine(folder, safe_name + ".wav")
node.Export(export_path)
count += 1
append_log("{0} -> OK\n".format(export_name))
except Exception as e:
failed += 1
append_log("{0} -> FAIL: {1}\n".format(export_name, str(e)))
# サマリー
append_log("=== Export Summary ===\n")
append_log("Success: {0}\n".format(count))
append_log("Failed: {0}\n".format(failed))
# ログファイルを閉じる
close_log()
# 結果表示
msg = "{0} wav files were successfully exported to {1}".format(count, folder)
if failed > 0:
msg += "\n{0} files failed to export (see log for details)".format(failed)
BrawlAPI.ShowMessage(msg, SCRIPT_NAME)
else:
BrawlAPI.ShowError('Cannot find Root Node (is a file open?)', 'Error')
# スクリプト実行
try:
main()
except Exception as e:
append_log("\n=== FATAL ERROR ===\n")
append_log(str(e))
close_log()
BrawlAPI.ShowError("予期しないエラー: {0}".format(str(e)), SCRIPT_NAME)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment