テクノロジー · 実用ガイド
Bambu Studioのプリセットが消えた?再インストール前にファイルを監査
メニューにないだけではJSONの削除を証明できません。設定ツリーを保全し、ユーザープリセットのハッシュと継承元を確認します。

Bambu Studioからカスタムフィラメントプリセットが消えたとき、ばらばらのJSONを稼働中プロファイルへ戻したり、上書き再インストールしたりするところから始めないでください。現在の報告には、継承型プリセットがディスクに残ったまま非表示になる例と、更新後にシステムプロファイル一式が空になる例があります。同じ表示症状でも、可視性、親プリセット欠落、破損、実際のファイル欠落を区別する必要があります。
このガイドは、保全したBambu Studio設定ツリーのコピーから読み取り専用の証拠CSVを作ります。各ユーザープリセットについて、アカウント範囲、相対パス、正確なバイト数、SHA-256、名前、inherits、対応プリンター、root-preset・parent-found・parent-missing・unreadableの状態を記録します。クラウドへログインせず、稼働中設定を書き換えず、削除済みファイルの復元を約束しません。
Studioを変更する前に証拠を固定する
Bambu Studioを完全に終了し、そのインストールが実際に使う設定ルートを確認して、別名の完全コピーを作ります。filamentだけではなく全体を保全し、可能なら時刻と権限も保持します。清掃、同期、インポート、リセット、再インストールは、非表示と欠落を区別する証拠を変えるため先に行いません。
Bambu Studioのバージョン、OS、選択中のプリンターとノズル、コピー時刻を記録します。まだ見えるプリセットがあれば、その作業セッション中に文書化されたプリセットバンドルのエクスポートも行います。可視エクスポートとディスク監査は別の問いに答えます。
ユーザープリセットとシステム親を分ける
ユーザーフィラメントプリセットはdefaultやアカウント別など複数範囲に置かれます。また、全設定を持たず、inheritsでシステムプリセットとの差分だけを表す場合があります。JSONを見つけても、それだけでStudioが読み込めるとは限りません。
監査はsystem/BBL/filamentの名前付きシステムプリセットを索引化し、各ユーザープリセットのinheritsを照合します。同名ファイルを自動的に同一とせず、JSON名と正確なバイトを記録し、重複キーを含むJSONは最後の値を黙って採用せず拒否します。
保全コピーだけで監査する
次のスクリプトをbambu_preset_audit.pyとして保存します。Python 3.12または互換Python 3で、保全した設定ルートと、その外側に作る新しいCSVパスを渡します。既存レポートは上書きせず、シンボリックリンクを飛ばし、入力ツリーを書きません。
Run this exact reviewed script from a copy of the configuration tree, not the live tree: ```python #!/usr/bin/env python3 """Read-only inventory for Bambu Studio user filament preset JSON files.""" from __future__ import annotations import argparse import csv import hashlib import json from pathlib import Path def object_no_duplicates(pairs): result = {} for key, value in pairs: if key in result: raise ValueError(f"duplicate JSON key: {key}") result[key] = value return result def load_json(path: Path): raw = path.read_bytes() value = json.loads(raw.decode("utf-8-sig"), object_pairs_hook=object_no_duplicates) if not isinstance(value, dict): raise ValueError("top-level JSON value is not an object") return raw, value def text_list(value): if value is None: return [] if isinstance(value, str): return [value] if isinstance(value, list) and all(isinstance(item, str) for item in value): return value raise ValueError("compatible_printers is not a string list") def system_names(root: Path): names = {} system_root = root / "system" / "BBL" / "filament" if not system_root.is_dir(): return names for path in sorted(system_root.rglob("*.json")): if path.is_symlink() or not path.is_file(): continue try: _, data = load_json(path) name = data.get("name") if isinstance(name, str) and name: names.setdefault(name, []).append(path.relative_to(root).as_posix()) except (OSError, UnicodeError, ValueError, json.JSONDecodeError): continue return names def audit(root: Path): parents = system_names(root) user_root = root / "user" rows = [] if not user_root.is_dir(): return rows for scope in sorted(user_root.iterdir()): filament = scope / "filament" if scope.is_symlink() or not scope.is_dir() or not filament.is_dir(): continue for path in sorted(filament.rglob("*.json")): if path.is_symlink() or not path.is_file(): continue row = { "account_scope": scope.name, "relative_path": path.relative_to(root).as_posix(), "bytes": path.stat().st_size, "sha256": "", "preset_name": "", "inherits": "", "parent_status": "unreadable", "parent_paths": "", "compatible_printers": "", "error": "", } try: raw, data = load_json(path) row["sha256"] = hashlib.sha256(raw).hexdigest() name = data.get("name", path.stem) if not isinstance(name, str): raise ValueError("name is not a string") inherits = data.get("inherits", "") if not isinstance(inherits, str): raise ValueError("inherits is not a string") printers = text_list(data.get("compatible_printers")) row["preset_name"] = name row["inherits"] = inherits row["compatible_printers"] = " | ".join(printers) if not inherits: row["parent_status"] = "root-preset" elif inherits in parents: row["parent_status"] = "parent-found" row["parent_paths"] = " | ".join(parents[inherits]) else: row["parent_status"] = "parent-missing" except (OSError, UnicodeError, ValueError, json.JSONDecodeError) as exc: row["error"] = str(exc) rows.append(row) return rows def main(): parser = argparse.ArgumentParser() parser.add_argument("config_root", type=Path) parser.add_argument("report_csv", type=Path) args = parser.parse_args() root = args.config_root.resolve(strict=True) report = args.report_csv.resolve() if not root.is_dir(): raise SystemExit("config_root is not a directory") if report == root or root in report.parents: raise SystemExit("report_csv must be outside config_root") rows = audit(root) fields = [ "account_scope", "relative_path", "bytes", "sha256", "preset_name", "inherits", "parent_status", "parent_paths", "compatible_printers", "error", ] with report.open("x", encoding="utf-8-sig", newline="") as handle: writer = csv.DictWriter(handle, fieldnames=fields) writer.writeheader() writer.writerows(rows) print(json.dumps({"config_root": str(root), "report_csv": str(report), "rows": len(rows)})) if __name__ == "__main__": main() ```
コマンドと出力境界を確認する
例: python3 bambu_preset_audit.py '/evidence/BambuStudio-copy' '/evidence/bambu-preset-report.csv'。第二パスは設定コピーの外でなければなりません。端末には解決済み入力、レポートパス、行数だけを出し、詳細はCSVへ保存します。スクリプトとレポートのハッシュも一緒に保全します。
レビュー済みヘルパーは4,697バイト、SHA-256は4711e9c5db94afee575fc6dbbc2a206a29178eeae4ce17387db8a6159a21cf0です。CPython 3.12.14で、ルート、親解決、親欠落、重複キー破損JSONのフィクスチャに合格しました。これは分類器の境界を示すだけで、実アカウントやプリンター互換性を証明しません。
修復を選ぶ前に全行を読む
root-presetは親宣言なし、parent-foundはinherits名のシステム親が少なくとも一つある状態です。parent_pathsとcompatible_printersを一緒に確認します。parent-missingはユーザーファイルはあるが親が見つからない状態、unreadableはパスとエラーを残しつつ破損JSONを有効扱いしない状態です。
統合前にaccount_scopeを比べます。同名でもバイトが違うことがあります。SHA-256は正確な内容同一性であり、品質や互換性の判定ではありません。意図的な統合をパスとハッシュが裏付けない限り、別々に扱います。
証拠に次の分岐を選ばせる
必要ファイルと親がそろう場合は、まず選択プリンター/ノズルと非互換プリセットの非表示を確認し、見えるうちにエクスポートします。稼働中JSONを直接編集しません。親が欠ける場合はユーザーファイルを保全し、該当バージョンの信頼できるシステム層だけを修復します。
unreadable JSONはコピーで調査し、既知バックアップと比較します。唯一の証拠を正規化しません。ユーザーファイル自体がなければ監査で再作成はできず、既知バックアップ、可視エクスポート、ベンダー支援が必要です。
完了条件と限界を明確にする
コピー内の各ユーザー範囲のフィラメントJSONが全てCSVにあり、CSVがコピー外にあり、parent-missingとunreadableを確認した時点で証拠段階が完了です。修復成功は別で、証拠保全後にStudioを開き、対象プリンター/ノズルと値を確認します。
この手順は材料安全性、プリンター適合性、クラウド同期、全過去報告を診断しません。稼働中ツリーを書き換える前に止まります。表示とCSVが矛盾する場合は、コピーとCSVを保持してパス、ハッシュ、親状態、バージョンをサポートへ渡します。
