Obsidianで画像のコピペを自動でWebPに変換するプラグインを作った
はじめに
Obsidianで画像を多用していると、Vaultのサイズがどんどん膨れ上がっていく経験はないでしょうか。特にスクリーンショットを頻繁に貼り付ける場合、PNGやJPEG形式の画像ファイルがストレージを圧迫します。
この問題を解決するため、クリップボードから画像をペーストする際に自動的にWebP形式に変換するObsidianプラグイン「Paste Image as WebP」を開発しました。本記事では、WebP形式の利点とプラグインの機能、そして開発の過程について解説します。
WebP形式の利点
WebPは、Googleが開発した画像フォーマットで、従来のPNGやJPEGと比較して以下のような優位性があります。
ファイルサイズの削減
WebPの最大の特徴は、高い圧縮率です。同程度の画質を保ちながら、PNGやJPEGと比較して20〜50%程度ファイルサイズを削減できます。
具体的な例を挙げると、4096×4096ピクセルのスクリーンショットの場合:
- PNG形式:約8〜12MB
- JPEG形式(品質85%):約2〜4MB
- WebP形式(品質85%):約1〜2MB
この差は、画像を多用するVaultでは大きな影響を与えます。
透過対応
WebPは、PNG同様にアルファチャンネル(透過)をサポートしています。そのため、背景が透明な画像もそのまま扱うことができます。
ブラウザ対応
現在、主要なブラウザはすべてWebPをサポートしており、Obsidianでも問題なく表示できます。

プラグインの機能
基本機能
「Paste Image as WebP」プラグインは、以下の基本機能を提供します。
- 自動変換:クリップボードから画像をペースト(Ctrl+V / Cmd+V)すると、自動的にWebP形式に変換して保存
-
エディタへの自動挿入:変換後の画像を
![[ファイル名.webp]]形式で自動的にエディタに挿入 -
重複ファイルの処理:同名ファイルが存在する場合、自動的に連番を追加(例:
image-1.webp,image-2.webp)
ファイル名のカスタマイズ
ファイル名は2つの形式から選択できます。
固定名形式
同じファイル名で保存します。例えば、image.webpという固定名を設定すると、すべての画像がこの名前で保存されます(重複時は自動的に連番が追加されます)。
タイムスタンプ形式
日時をベースにしたファイル名を生成します。フォーマットは自由にカスタマイズ可能で、以下のプレースホルダーを使用できます。
-
YYYY:年(4桁) -
MM:月(2桁) -
DD:日(2桁) -
HH:時(2桁、24時間形式) -
mm:分(2桁) -
ss:秒(2桁)
デフォルトのYYYYMMDDHHmmss形式では、20231116143025.webpのようなファイル名が生成されます。カスタム例として、YYYY-MM-DD_HHmmssとすると2023-11-16_143025.webpという形式になります。
保存先の設定
画像の保存先は3つのオプションから選択できます。
-
現在のノートと同じフォルダ:ノートと同じディレクトリに指定したフォルダ名(デフォルト:
attachments)を作成して保存 - Vaultルート:Vaultのルートに指定したフォルダを作成して保存
-
カスタムパス:任意のパスを指定(例:
project/images)
WebP品質の調整
WebPの品質は0.1〜1.0の範囲で調整できます。デフォルトは0.85で、ファイルサイズと画質のバランスが取れた値です。
- 1.0:最高品質(ファイルサイズ大)
- 0.85:推奨値(バランス型)
- 0.5〜0.7:低品質(ファイルサイズ重視)
セキュリティ機能
プラグインには、以下のセキュリティ対策が実装されています。
- パストラバーサル攻撃の防止:ファイル名とフォルダパスをサニタイズし、Vault外部への書き込みを防止
- DoS攻撃の防止:画像の最大ピクセル数(デフォルト:16,777,216 = 4096×4096)と最大ファイルサイズ(デフォルト:10MB)を制限
- ファイル名インジェクションの防止:特殊文字を適切に処理
- 無限ループの防止:重複ファイル名チェックの試行回数を制限
これらの設定は、プラグインの設定画面から変更できます。

技術的な実装
開発環境
プラグインは以下の技術スタックで開発しました。
- 言語:TypeScript
- ビルドツール:esbuild
- ターゲット環境:Obsidian Plugin API
プロジェクト構成
obsidian_extension/
├── main.ts # メインのプラグインロジック
├── manifest.json # プラグインのメタデータ
├── package.json # npm設定
├── tsconfig.json # TypeScript設定
├── esbuild.config.mjs # esbuild設定
└── styles.css # スタイルシート
TypeScriptからJavaScriptへのビルド
Obsidianプラグインは、最終的にJavaScriptファイル(main.js)として配布する必要があります。開発ではTypeScriptを使用し、esbuildでバンドル・トランスパイルしています。
package.jsonのスクリプト設定:
{
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production"
}
}
開発時はnpm run devでファイル変更を監視し、自動的にリビルドされます。本番ビルドはnpm run buildで実行します。
esbuildの設定
esbuildは高速なJavaScriptバンドラーで、TypeScriptのトランスパイルも行えます。設定ファイル(esbuild.config.mjs)では、以下を指定しています。
{
entryPoints: ["main.ts"],
bundle: true,
external: ["obsidian", "electron", ...],
format: "cjs",
target: "es2018",
outfile: "main.js"
}
重要なポイント:
-
external:Obsidianが提供するモジュールは外部依存として扱う -
format: "cjs":CommonJS形式で出力 -
target: "es2018":ES2018をターゲットに設定
画像変換のコアロジック
画像の変換処理は、ブラウザのCanvas APIを使用しています。
private async convertToWebP(file: File): Promise<Blob> {
return new Promise((resolve, reject) => {
const img = new Image();
const reader = new FileReader();
reader.onload = (e) => {
img.onload = () => {
// 画像サイズの検証
this.validateImageDimensions(img.width, img.height);
// Canvasに描画
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// WebPに変換
canvas.toBlob(
(blob) => {
if (blob) {
resolve(blob);
} else {
reject(new Error('Failed to convert to WebP'));
}
},
'image/webp',
this.settings.webpQuality
);
};
img.src = e.target?.result as string;
};
reader.readAsDataURL(file);
});
}
この実装のポイント:
- FileReaderでファイルをData URLとして読み込み
- Image要素にロード
- Canvasに描画
-
canvas.toBlob()でWebP形式に変換(品質指定可能)
ファイル保存処理
Obsidian Vault APIを使用してファイルを保存します。
private async saveImage(blob: Blob, filename: string, view: MarkdownView): Promise<string> {
// フォルダパスの決定
let folder: string;
if (this.settings.imageFolderLocation === 'current-folder') {
const currentFile = view.file;
const baseFolder = currentFile?.parent?.path || '';
folder = baseFolder ? `${baseFolder}/${folderName}` : folderName;
}
// ... その他のロケーション処理
// フォルダが存在しない場合は作成
const folderExists = await this.app.vault.adapter.exists(folder);
if (!folderExists) {
await this.app.vault.createFolder(folder);
}
// 重複チェックと保存
let filepath = `${folder}/${filename}`;
let counter = 1;
while (await this.app.vault.adapter.exists(filepath)) {
const nameWithoutExt = filename.replace('.webp', '');
filepath = `${folder}/${nameWithoutExt}-${counter}.webp`;
counter++;
}
// ArrayBufferに変換して保存
const arrayBuffer = await blob.arrayBuffer();
await this.app.vault.createBinary(filepath, arrayBuffer);
return filepath;
}
クリップボードイベントのハンドリング
Obsidianのエディタペーストイベントをインターセプトします。
async onload() {
await this.loadSettings();
this.registerEvent(
this.app.workspace.on('editor-paste', this.handlePaste.bind(this))
);
this.addSettingTab(new PasteImageAsWebPSettingTab(this.app, this));
}
private async handlePaste(evt: ClipboardEvent, editor: Editor, view: MarkdownView) {
const files = evt.clipboardData?.files;
if (!files || files.length === 0) {
return; // 画像がない場合は通常のペースト処理
}
const imageFiles = Array.from(files).filter(file =>
file.type.startsWith('image/')
);
if (imageFiles.length === 0) {
return;
}
evt.preventDefault(); // デフォルトのペースト動作を防ぐ
for (const file of imageFiles) {
await this.processImage(file, editor, view);
}
}
インストール方法
コミュニティプラグインから(現在リリース申請中です)
プルリクエストが通ったら、コミュニティプラグインからインストールできます。
今しばらくお待ちくださいませ (+_+)
手動インストール
-
GitHubリリースページから
main.js、manifest.json、styles.cssをダウンロード - Vaultのプラグインフォルダに
paste-image-as-webpフォルダを作成


-
ダウンロードしたファイルを配置

-
Obsidianを再起動してプラグインを有効化

使い方
- プラグインを有効化
- 設定画面で好みに合わせてカスタマイズ
- 画像をクリップボードにコピー
- Obsidianのエディタでペースト(Ctrl+V / Cmd+V)
- 自動的にWebP形式で保存され、エディタに挿入される

まとめ
「Paste Image as WebP」プラグインを使用することで、以下のメリットが得られます。
- Vaultのサイズ削減:画像ファイルサイズが20〜50%削減され、ストレージを節約
- シームレスな体験:通常のペースト操作と変わらない使い勝手
- 柔軟な設定:ファイル名、保存先、品質を自由にカスタマイズ可能
- セキュリティ:各種攻撃に対する防御機能を実装
画像を多用するObsidianユーザーにとって、このプラグインはVault管理の負担を大きく軽減できるツールとなるはずです。
GitHubでオープンソースとして公開していますので、バグ報告や機能要望はIssuesでお待ちしています。
リンク
補足
基本的な使い方
1. プラグインの有効化
- Obsidianの設定を開く(歯車アイコン)
- 左サイドバーから「コミュニティプラグイン」を選択
- 「Paste Image as WebP」を探して「有効化」をクリック
2. 画像の貼り付け手順
- 任意の画像をクリップボードにコピー
- スクリーンショットを撮る(Windows:
Win + Shift + S、Mac:Cmd + Shift + 4) - ブラウザや画像ビューアーで画像を右クリック→「コピー」
- 画像ファイルをコピー(
Ctrl + C/Cmd + C)
- スクリーンショットを撮る(Windows:
- Obsidianのエディタでペースト
-
Ctrl + V(Windows/Linux) -
Cmd + V(Mac)
-
- 自動的に以下が実行される
- 画像がWebP形式に変換
- 指定したフォルダに保存
- エディタに
![[ファイル名.webp]]形式で挿入 - 通知メッセージが表示される
設定項目の詳細
プラグインの設定画面は、「設定」→「コミュニティプラグイン」→「Paste Image as WebP」の歯車アイコンから開けます。
ファイル名設定(Filename format)
Filename format(ファイル名形式)
デフォルト値: Timestamp(タイムスタンプ)
選択肢:
-
Fixed name(固定名):毎回同じファイル名で保存 -
Timestamp(タイムスタンプ):日時ベースのファイル名
設定方法:
ドロップダウンメニューから選択します。
Fixed filename(固定ファイル名)
デフォルト値: image
適用条件: Filename formatが「Fixed name」の場合のみ表示
動作:
- 設定した名前で保存される(例:
image.webp) - 同名ファイルが存在する場合、自動的に連番が追加される
- 1枚目:
image.webp - 2枚目:
image-1.webp - 3枚目:
image-2.webp
設定方法:
- 1枚目:
- Filename formatを「Fixed name」に変更
- テキストフィールドに好きな名前を入力(拡張子は不要)
使用例:
設定値: screenshot
結果: screenshot.webp, screenshot-1.webp, screenshot-2.webp...
Timestamp format(タイムスタンプフォーマット)
デフォルト値: YYYYMMDDHHmmss
適用条件: Filename formatが「Timestamp」の場合のみ表示
使用可能なプレースホルダー:
-
YYYY:年(4桁)例:2024 -
MM:月(2桁)例:01, 12 -
DD:日(2桁)例:01, 31 -
HH:時(2桁、24時間形式)例:00, 23 -
mm:分(2桁)例:00, 59 -
ss:秒(2桁)例:00, 59
設定方法:
- Filename formatを「Timestamp」に変更
- テキストフィールドにフォーマットを入力
- リアルタイムでサンプルが表示される
フォーマット例:
| フォーマット | 出力例 | 用途 |
|------------|--------|------|
|YYYYMMDDHHmmss|20241130143025.webp| デフォルト、秒単位で一意 |
|YYYY-MM-DD_HHmmss|2024-11-30_143025.webp| 読みやすい形式 |
|YYYYMMDD_HH-mm-ss|20241130_14-30-25.webp| 時刻を区切る |
|YYYY-MM-DD|2024-11-30.webp| 日付のみ(1日に1枚のみの場合) |
|YYYYMMDD-HHmm|20241130-1430.webp| 分単位(秒は不要な場合) |
サンプル表示:
設定画面でフォーマットを入力すると、下部に現在時刻でのサンプルが表示されます。
Sample: 20241130143025.webp
保存先設定
Image folder location(画像フォルダの場所)
デフォルト値: Same folder as current note(現在のノートと同じフォルダ)
選択肢:
-
Same folder as current note:現在のノートと同じフォルダ -
Vault root:Vaultのルート -
Custom path:カスタムパス
設定方法:
ドロップダウンメニューから選択します。
各選択肢の動作:
1. Same folder as current note(推奨)
現在編集中のノートと同じフォルダに、指定したサブフォルダを作成して保存します。
例:
Vaultの構成:
├── Projects/
│ └── Project-A.md ← 現在編集中
└── Daily/
└── 2024-11-30.md
設定: Image folder name = "attachments"
保存先:
Projects/attachments/20241130143025.webp
メリット:
- ノートと画像が近くに配置される
- プロジェクトごとに画像を整理できる
- ノートを移動しても相対パスが維持される
2. Vault root
Vaultのルートに、指定したフォルダを作成して保存します。
例:
Vaultの構成:
├── Projects/
│ └── Project-A.md ← 現在編集中
└── attachments/ ← ここに保存される
└── 20241130143025.webp
メリット:
- すべての画像が1箇所に集約される
- 画像の一括管理が容易
デメリット: - ノート数が多いと画像フォルダが巨大になる
3. Custom path
任意のパスを指定して保存します。
例:
設定: Custom folder path = "resources/images"
保存先:
resources/images/20241130143025.webp
メリット:
- 完全に自由なフォルダ構造を実現
- 複数レベルのフォルダを指定可能
Image folder name(画像フォルダ名)
デフォルト値: attachments
適用条件: Image folder locationが「Custom path」以外の場合に表示
設定方法:
テキストフィールドにフォルダ名を入力します。
動作:
- フォルダが存在しない場合、自動的に作成される
- 既存のフォルダがある場合、そこに保存される
例:
設定値: images
結果:
- Same folder as current noteの場合: ノートのフォルダ/images/
- Vault rootの場合: Vaultルート/images/
Custom folder path(カスタムフォルダパス)
デフォルト値: project/images
適用条件: Image folder locationが「Custom path」の場合のみ表示
設定方法:
- Image folder locationを「Custom path」に変更
- テキストフィールドに完全なパスを入力
パス指定の規則:
- Vaultルートからの相対パス
-
/(スラッシュ)で区切る - 先頭や末尾のスラッシュは不要
例:
設定値: resources/screenshots
結果: Vaultルート/resources/screenshots/
設定値: work/projects/project-a/assets
結果: Vaultルート/work/projects/project-a/assets/
サンプル表示:
設定画面の下部に保存先のプレビューが表示されます。
Images will be saved to: project/images/
画質設定
Image quality (WebP)(画像品質)
デフォルト値: 0.85
範囲: 0.1〜1.0(スライダーで調整、0.05刻み)
説明:
- 1.0:最高品質(ファイルサイズが最大)
- 0.85:推奨値(品質とサイズのバランス)
- 0.5〜0.7:低品質(ファイルサイズ重視)
設定方法:
スライダーをドラッグして調整します。リアルタイムで値が表示されます。
品質とファイルサイズの目安:
| 品質設定 | ファイルサイズ | 画質 | 推奨用途 |
|---|---|---|---|
| 1.0 | 100% | 最高 | 写真の保管、印刷用 |
| 0.9 | 約80% | 非常に高い | 高品質が必要な画像 |
| 0.85 | 約70% | 高い | 一般的な用途(推奨) |
| 0.8 | 約60% | 高い | スクリーンショット |
| 0.7 | 約50% | 中程度 | 図表、ダイアグラム |
| 0.5 | 約30% | 低い | サムネイル、下書き |
| 実例(1920×1080のスクリーンショット): |
PNG形式: 約2.5MB
品質1.0: 約1.5MB(40%削減)
品質0.85: 約800KB(68%削減)← デフォルト
品質0.7: 約500KB(80%削減)
セキュリティ設定
Maximum image size(最大画像サイズ)
デフォルト値: 16777216(ピクセル)
説明:
画像の最大ピクセル数(幅 × 高さ)を制限します。
計算例:
- 16,777,216ピクセル = 4096 × 4096
- 4,194,304ピクセル = 2048 × 2048
- 67,108,864ピクセル = 8192 × 8192
設定方法:
テキストフィールドに数値を入力します。
推奨値:
| 用途 | 推奨値 | サイズ例 |
|---|---|---|
| 一般的な用途 | 16,777,216 | 4096×4096 |
| 高セキュリティ環境 | 4,194,304 | 2048×2048 |
| パワーユーザー | 67,108,864 | 8192×8192 |
| 目的: | ||
| 巨大な画像によるメモリ枯渇(DoS攻撃)を防ぎます。 | ||
| エラー時の挙動: | ||
| 制限を超える画像をペーストすると、エラーメッセージが表示され、画像は保存されません。 |
Image dimensions exceed maximum allowed size
Maximum file size (MB)(最大ファイルサイズ)
デフォルト値: 10 MB
説明:
ペースト可能な画像ファイルの最大サイズをMB単位で制限します。
設定方法:
テキストフィールドに数値を入力します(小数点も使用可能)。
推奨値:
| 用途 | 推奨値 |
|---|---|
| 一般的な用途 | 10 MB |
| 高セキュリティ環境 | 5 MB |
| パワーユーザー | 50 MB |
| 例: |
設定値: 5
結果: 5MB以下の画像のみペースト可能
設定値: 2.5
結果: 2.5MB以下の画像のみペースト可能
エラー時の挙動:
制限を超える画像をペーストすると、エラーメッセージが表示されます。
Image file size exceeds 10MB limit
実践的な設定例
例1: 日記用の設定(デフォルト推奨)
Filename format: Timestamp
Timestamp format: YYYYMMDDHHmmss
Image folder location: Same folder as current note
Image folder name: attachments
Image quality: 0.85
Maximum image size: 16777216
Maximum file size: 10 MB
動作:
Vaultの構成:
├── Daily/
│ ├── 2024-11-30.md ← 編集中
│ └── attachments/
│ └── 20241130143025.webp ← 保存される
例2: プロジェクト管理用の設定
Filename format: Fixed name
Fixed filename: screenshot
Image folder location: Same folder as current note
Image folder name: images
Image quality: 0.8
Maximum image size: 16777216
Maximum file size: 10 MB
動作:
Vaultの構成:
├── Projects/
│ ├── ProjectA/
│ │ ├── overview.md ← 編集中
│ │ └── images/
│ │ ├── screenshot.webp
│ │ ├── screenshot-1.webp
│ │ └── screenshot-2.webp
例3: 一元管理用の設定
Filename format: Timestamp
Timestamp format: YYYY-MM-DD_HHmmss
Image folder location: Vault root
Image folder name: assets
Image quality: 0.85
Maximum image size: 16777216
Maximum file size: 10 MB
動作:
Vaultの構成:
├── assets/
│ ├── 2024-11-30_143025.webp
│ ├── 2024-11-30_150312.webp
│ └── 2024-11-30_163540.webp
├── Projects/
│ └── overview.md ← どこから貼っても assets/ に保存
└── Daily/
└── 2024-11-30.md
例4: 高品質写真保存用
Filename format: Timestamp
Timestamp format: YYYY-MM-DD_HHmmss
Image folder location: Custom path
Custom folder path: media/photos
Image quality: 0.95
Maximum image size: 67108864
Maximum file size: 50 MB
用途: 写真をアーカイブとして保存する場合
トラブルシューティング
画像がペーストされない
確認事項:
- プラグインが有効化されているか
- クリップボードに画像データがあるか
- ファイルサイズや画像サイズが制限内か
対処法:
- コンソール(
Ctrl + Shift + I)でエラーを確認 - セキュリティ設定の制限を一時的に緩和して確認
フォルダが作成されない
原因:
親フォルダが存在しない場合、自動作成されません。
対処法:
- 手動で親フォルダを作成
- または、シンプルなフォルダ構造に変更
例:
設定: Custom folder path = "projects/work/screenshots"
親フォルダ "projects/work" が存在しない場合 → エラー
対処: 先に "projects/work" フォルダを手動で作成
同名ファイルが増え続ける
原因:
Fixed name形式で連番が増え続けている。
対処法:
- Timestamp形式に変更
- または、定期的に古い画像を整理
まとめ
「Paste Image as WebP」プラグインの設定は、用途に応じて柔軟にカスタマイズできます。
推奨設定:
- 一般ユーザー:デフォルト設定のまま
- こだわり派:Timestamp formatを読みやすい形式に
- 大量の画像を扱う:品質を0.7〜0.8に下げてファイルサイズを削減
自分の使い方に合わせて、最適な設定を見つけてください。
Discussion