diff --git a/.gitignore b/.gitignore
index a547bf3..bd6417a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ dist-ssr
*.njsproj
*.sln
*.sw?
+.agents/*
\ No newline at end of file
diff --git a/README.md b/README.md
index 086a62e..91f4deb 100644
--- a/README.md
+++ b/README.md
@@ -11,19 +11,23 @@
## ディレクトリ構成
-| パス | 内容 |
-| ---------------------- | ------------------------------------------------------------- |
-| `dist` | ビルド成果物の出力先ディレクトリ。`npm run build`で生成される |
-| `node_modules` | npmの依存パッケージ。`npm install`で生成される |
-| `public` | ビルド後にルートに置かれる。画像など |
-| `src/App.css` | スタイルシート |
-| `src/App.tsx` | フロントエンドの本体 |
-| `src-tauri/icons` | アプリケーションアイコン |
-| `src-tauri/src/lib.rs` | 変換処理のロジック |
-| `.gitignore` | Gitで管理しないファイルの設定 |
-| `package-lock.json` | npmの依存パッケージのバージョンを固定するためのファイル |
-| `package.json` | npmの設定ファイル |
-| `README.md` | この文章 |
+| パス | 内容 |
+| --------------------------- | ------------------------------------------------------------- |
+| `dist` | ビルド成果物の出力先ディレクトリ。`npm run build`で生成される |
+| `node_modules` | npmの依存パッケージ。`npm install`で生成される |
+| `public` | ビルド後にルートに置かれる。画像など |
+| `src/App.css` | スタイルシート |
+| `src/App.tsx` | フロントエンドの本体 |
+| `src-tauri/binaries` | FFmpegのバイナリファイル。sidecarで使用されている |
+| `src-tauri/icons` | アプリケーションアイコン |
+| `src-tauri/src/lib.rs` | 変換処理のロジック |
+| `src-tauri/.gitignore` | Gitで管理しないファイルの設定(バックエンド) |
+| `src-tauri/tauri.conf.json` | Tauriの設定ファイル |
+| `src-tauri/Cargo.toml` | Rustの設定ファイル |
+| `.gitignore` | Gitで管理しないファイルの設定 |
+| `package-lock.json` | npmの依存パッケージのバージョンを固定するためのファイル |
+| `package.json` | npmの設定ファイル |
+| `README.md` | この文章 |
## インストール
@@ -37,11 +41,6 @@
winget install --id Rustlang.Rustup
```
-3. FFmpegのインストール
- ```bash
- winget install -e --id Gyan.FFmpeg
- ```
-
### MacOSの場合
1. Rustのインストール
@@ -60,20 +59,57 @@
source ~/.zshrc
```
-3. FFmpegのインストール
+## FFmpegのバイナリファイルの設置
+
+1. `src-tauri/binaries`ディレクトリを作成
+
+2. Linux用のバイナリファイルの用意
+ 1. https://github.com/BtbN/FFmpeg-Builds/releases から`ffmpeg-n8.1-latest-linux64-gpl-8.1.tar.xz`をダウンロード
+ 2. 解凍して出てくる`bin/ffmpeg`を`src-tauri/binaries`配下に設置
+ 3. `fmpeg-x86_64-unknown-linux-gnu`にリネームする
+
+3. Windows用のバイナリファイルの用意
+ 1. https://www.gyan.dev/ffmpeg/builds/ から`ffmpeg-release-full.7z`をダウンロード
+ 2. 解凍して出てくる`bin/ffmpeg.exe`を`src-tauri/binaries`配下に設置
+ 3. `ffmpeg-x86_64-pc-windows-msvc.exe`にリネームする
+
+4. MacOS(Intel)用のバイナリファイルの用意
+ 1. https://evermeet.cx/ffmpeg/ から`ffmpeg-9.0.1.7z`をダウンロード
+ 2. 解凍して出てくる`ffmpeg`を`src-tauri/binaries`配下に設置
+ 3. `ffmpeg-x86_64-apple-darwin`にリネームする
+
+5. MacOS(Apple Silicon)用のバイナリファイルの用意
+ 1. https://www.osxexperts.net/ で"Download ffmpeg 9.0 (Apple Silicon)"をクリックして`ffmpeg9arm.zip`をダウンロード
+ 2. 解凍して出てくる`ffmpeg`を`src-tauri/binaries`配下に設置
+ 3. `ffmpeg-aarch64-apple-darwin`にリネームする
+
+6. バイナリファイルの実行権限を付与(初回のみ)
+
```bash
- brew install ffmpeg-full
+ chmod +x src-tauri/binaries/ffmpeg-*
```
## 開発
-- 依存パッケージのインストール
+- 依存パッケージのインストール(`package.json`が更新されたときに実行)
```bash
npm install
```
-- 開発環境でアプリケーションを起動(ctrl + C / ⌃Cで終了)
+- 新たなパッケージのインストール
+
+ ```bash
+ npm install <パッケージ名>
+ ```
+
+- tauriのプラグインのインストール
+
+ ```bash
+ npm run tauri add <プラグイン名>
+ ```
+
+- 開発環境でアプリケーションを起動(`ctrl + C` / `⌃C`で終了)
```bash
npm run tauri dev
@@ -85,7 +121,20 @@
npm run tauri build
```
-- FFmpegでファイル形式を変換する例(プロジェクトのルートにinput.jpgを置く)
+- FFmpegのインストール(バイナリファイルを設置するため、インストールしなくてもアプリケーションは動作する)
+ - Windowsの場合
+
+ ```bash
+ winget install -e --id Gyan.FFmpeg
+ ```
+
+ - MacOSの場合
+
+ ```bash
+ brew install ffmpeg-full
+ ```
+
+- FFmpegでファイル形式を変換する例(プロジェクトのルートに`input.jpg`を置く)
```bash
ffmpeg -i input.jpg output.png
```
diff --git a/package-lock.json b/package-lock.json
index 9dc01f7..3da5d1e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,11 +8,15 @@
"name": "henkanhakase",
"version": "0.1.0",
"dependencies": {
+ "@ffmpeg/core": "^0.12.10",
+ "@ffmpeg/ffmpeg": "^0.12.15",
+ "@ffmpeg/util": "^0.12.2",
"@tailwindcss/vite": "^4.3.3",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "^2.7.2",
"@tauri-apps/plugin-fs": "^2.5.1",
"@tauri-apps/plugin-opener": "^2",
+ "@tauri-apps/plugin-shell": "^2.3.5",
"browser-image-compression": "^2.0.2",
"react": "^19.1.0",
"react-dom": "^19.1.0",
@@ -725,6 +729,45 @@
"node": ">=18"
}
},
+ "node_modules/@ffmpeg/core": {
+ "version": "0.12.10",
+ "resolved": "https://registry.npmjs.org/@ffmpeg/core/-/core-0.12.10.tgz",
+ "integrity": "sha512-dzNplnn2Nxle2c2i2rrDhqcB19q9cglCkWnoMTDN9Q9l3PvdjZWd1HfSPjCNWc/p8Q3CT+Es9fWOR0UhAeYQZA==",
+ "license": "GPL-2.0-or-later",
+ "engines": {
+ "node": ">=16.x"
+ }
+ },
+ "node_modules/@ffmpeg/ffmpeg": {
+ "version": "0.12.15",
+ "resolved": "https://registry.npmjs.org/@ffmpeg/ffmpeg/-/ffmpeg-0.12.15.tgz",
+ "integrity": "sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==",
+ "license": "MIT",
+ "dependencies": {
+ "@ffmpeg/types": "^0.12.4"
+ },
+ "engines": {
+ "node": ">=18.x"
+ }
+ },
+ "node_modules/@ffmpeg/types": {
+ "version": "0.12.4",
+ "resolved": "https://registry.npmjs.org/@ffmpeg/types/-/types-0.12.4.tgz",
+ "integrity": "sha512-k9vJQNBGTxE5AhYDtOYR5rO5fKsspbg51gbcwtbkw2lCdoIILzklulcjJfIDwrtn7XhDeF2M+THwJ2FGrLeV6A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.x"
+ }
+ },
+ "node_modules/@ffmpeg/util": {
+ "version": "0.12.2",
+ "resolved": "https://registry.npmjs.org/@ffmpeg/util/-/util-0.12.2.tgz",
+ "integrity": "sha512-ouyoW+4JB7WxjeZ2y6KpRvB+dLp7Cp4ro8z0HIVpZVCM7AwFlHa0c4R8Y/a4M3wMqATpYKhC7lSFHQ0T11MEDw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.x"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -1613,6 +1656,15 @@
"@tauri-apps/api": "^2.11.0"
}
},
+ "node_modules/@tauri-apps/plugin-shell": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.3.5.tgz",
+ "integrity": "sha512-jewtULhiQ7lI7+owCKAjc8tYLJr92U16bPOeAa472LHJdgaibLP83NcfAF2e+wkEcA53FxKQAZ7byDzs2eeizg==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@tauri-apps/api": "^2.10.1"
+ }
+ },
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
diff --git a/package.json b/package.json
index 0c0fada..591dd26 100644
--- a/package.json
+++ b/package.json
@@ -10,11 +10,15 @@
"tauri": "tauri"
},
"dependencies": {
+ "@ffmpeg/core": "^0.12.10",
+ "@ffmpeg/ffmpeg": "^0.12.15",
+ "@ffmpeg/util": "^0.12.2",
"@tailwindcss/vite": "^4.3.3",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "^2.7.2",
"@tauri-apps/plugin-fs": "^2.5.1",
"@tauri-apps/plugin-opener": "^2",
+ "@tauri-apps/plugin-shell": "^2.3.5",
"browser-image-compression": "^2.0.2",
"react": "^19.1.0",
"react-dom": "^19.1.0",
diff --git a/public/tauri.svg b/public/tauri.svg
deleted file mode 100644
index 31b62c9..0000000
--- a/public/tauri.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/public/vite.svg b/public/vite.svg
deleted file mode 100644
index e7b8dfb..0000000
--- a/public/vite.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src-tauri/.gitignore b/src-tauri/.gitignore
index b21bd68..fe7c329 100644
--- a/src-tauri/.gitignore
+++ b/src-tauri/.gitignore
@@ -5,3 +5,5 @@
# Generated by Tauri
# will have schema files for capabilities auto-completion
/gen/schemas
+
+/binaries/
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index 2411fd0..a7a22d0 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -854,6 +854,15 @@ version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
+[[package]]
+name = "encoding_rs"
+version = "0.8.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
+dependencies = [
+ "cfg-if",
+]
+
[[package]]
name = "endi"
version = "1.1.1"
@@ -1428,6 +1437,7 @@ dependencies = [
"tauri-plugin-dialog",
"tauri-plugin-fs",
"tauri-plugin-opener",
+ "tauri-plugin-shell",
]
[[package]]
@@ -2306,6 +2316,16 @@ dependencies = [
"pin-project-lite",
]
+[[package]]
+name = "os_pipe"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
+dependencies = [
+ "libc",
+ "windows-sys 0.61.2",
+]
+
[[package]]
name = "pango"
version = "0.18.3"
@@ -3039,12 +3059,44 @@ dependencies = [
"digest",
]
+[[package]]
+name = "shared_child"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7"
+dependencies = [
+ "libc",
+ "sigchld",
+ "windows-sys 0.60.2",
+]
+
[[package]]
name = "shlex"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
+[[package]]
+name = "sigchld"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1"
+dependencies = [
+ "libc",
+ "os_pipe",
+ "signal-hook",
+]
+
+[[package]]
+name = "signal-hook"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
[[package]]
name = "signal-hook-registry"
version = "1.4.8"
@@ -3488,6 +3540,27 @@ dependencies = [
"zbus",
]
+[[package]]
+name = "tauri-plugin-shell"
+version = "2.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8457dbf9e2bab1edd8df22bb2c20857a59a9868e79cb3eac5ed639eec4d0c73b"
+dependencies = [
+ "encoding_rs",
+ "log",
+ "open",
+ "os_pipe",
+ "regex",
+ "schemars 0.8.22",
+ "serde",
+ "serde_json",
+ "shared_child",
+ "tauri",
+ "tauri-plugin",
+ "thiserror 2.0.18",
+ "tokio",
+]
+
[[package]]
name = "tauri-runtime"
version = "2.11.3"
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 2d27dd7..26509d8 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -24,4 +24,5 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
tauri-plugin-dialog = "2"
tauri-plugin-fs = "2"
+tauri-plugin-shell = "2"
diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json
index 3b96e47..1f7927c 100644
--- a/src-tauri/capabilities/default.json
+++ b/src-tauri/capabilities/default.json
@@ -10,6 +10,7 @@
"opener:default",
"dialog:default",
"fs:default",
- "fs:allow-write-file"
+ "fs:allow-write-file",
+ "shell:default"
]
}
\ No newline at end of file
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index aa18a96..da875b8 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -1,16 +1,61 @@
-// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
+use tauri_plugin_shell::ShellExt;
+
#[tauri::command]
-fn greet(name: &str) -> String {
- format!("Hello, {}! You've been greeted from Rust!", name)
+async fn convert_file(
+ app: tauri::AppHandle,
+ data: Vec