🎯 はじめに
AviUtl2は非常に拡張性の高い動画編集ソフトですが、
すべてのファイル形式を直接読み込めるわけではありません。
たとえば、
- Photoshop形式(PSD)
- WebP / HEIC / 独自RGBA形式
- AI生成画像やキャッシュ画像シーケンス
といった形式は、標準の input.aui2 では対応していません。
そこで登場するのが 入力プラグイン (Input Plugin) です。
入力プラグインを作成することで、AviUtl2が本来扱えない形式でも、
直接タイムラインに配置できるようになります。
本記事では、Delphiを使ってAviUtl2用入力プラグインを自作し、
JPEG画像を表示する最小サンプルを作成します。
🧩 開発環境
| 項目 | 内容 |
|---|---|
| 開発言語 | Delphi (RAD Studio / Embarcadero Delphi 10以降) |
| 対象バージョン | AviUtl2 β17 SDK |
| プラグイン形式 |
.aui2 (Input Plugin) |
| 動作環境 | Windows 10 / 11 |
🔧 プラグインの概要
このサンプルは、AviUtl2にJPEG画像を1フレーム映像として読み込む
最小構成の入力プラグインです。
| 機能 | 内容 |
|---|---|
| 対応形式 |
.jpg, .jpeg
|
| 出力形式 | RGBA 32bit (BGRA順) |
| フレーム数 | 1フレーム固定 |
| フレームレート | 30fps |
| 音声 | 非対応 |
| 設定ダイアログ | RGB色設定の簡易サンプルを実装 |
📂 プロジェクト構成
AviUtl2InputSample/
├─ AviUtl2InputSample.dpr # メインソース(DLL本体)
├─ AviUtl2InputSample.dproj # Delphi プロジェクトファイル
└─ README.md # GitHub用説明ファイル
library AviUtl2InputSample;
uses
Winapi.Windows,
Winapi.MMSystem,
System.SysUtils,
Vcl.Graphics,
Vcl.Imaging.jpeg;
type
PWAVEFORMATEX = ^WAVEFORMATEX;
WAVEFORMATEX = record
wFormatTag: Word;
nChannels: Word;
nSamplesPerSec: Cardinal;
nAvgBytesPerSec: Cardinal;
nBlockAlign: Word;
wBitsPerSample: Word;
cbSize: Word;
end;
type
LPCWSTR = PWideChar;
INPUT_HANDLE = Pointer;
PBITMAPINFOHEADER = ^BITMAPINFOHEADER;
TInputInfo = record
flag: Integer;
rate, scale: Integer;
n: Integer;
format: PBITMAPINFOHEADER;
format_size: Integer;
audio_n: Integer;
audio_format: PWAVEFORMATEX;
audio_format_size: Integer;
end;
PInputInfo = ^TInputInfo;
const
INPUT_INFO_FLAG_VIDEO = 1;
INPUT_PLUGIN_FLAG_VIDEO = 1;
type
TInputPluginTable = record
flag: Integer;
name: LPCWSTR;
filefilter: LPCWSTR;
information: LPCWSTR;
func_open: function(fileName: LPCWSTR): INPUT_HANDLE; cdecl;
func_close: function(ih: INPUT_HANDLE): BOOL; cdecl;
func_info_get: function(ih: INPUT_HANDLE; info: PInputInfo): BOOL; cdecl;
func_read_video: function(ih: INPUT_HANDLE; frame: Integer; buf: Pointer): Integer; cdecl;
func_read_audio: function(ih: INPUT_HANDLE; start, length: Integer; buf: Pointer): Integer; cdecl;
func_config: function(hwnd: HWND; hinst: HINST): BOOL; cdecl;
func_set_track: Pointer;
func_time_to_frame: Pointer;
end;
PInputPluginTable = ^TInputPluginTable;
type
PFileContext = ^TFileContext;
TFileContext = record
bitmap: TBitmap;
info: BITMAPINFOHEADER;
end;
function func_open(fileName: LPCWSTR): INPUT_HANDLE; cdecl;
var
jpeg: TJPEGImage;
bmp: TBitmap;
ctx: PFileContext;
begin
Result := nil;
if not FileExists(fileName) then Exit;
jpeg := TJPEGImage.Create;
bmp := TBitmap.Create;
try
jpeg.LoadFromFile(fileName);
bmp.Assign(jpeg);
bmp.PixelFormat := pf32bit;
New(ctx);
ctx^.bitmap := bmp;
FillChar(ctx^.info, SizeOf(ctx^.info), 0);
ctx^.info.biSize := SizeOf(BITMAPINFOHEADER);
ctx^.info.biWidth := bmp.Width;
ctx^.info.biHeight := bmp.Height;
ctx^.info.biPlanes := 1;
ctx^.info.biBitCount := 32;
ctx^.info.biCompression := BI_RGB;
ctx^.info.biSizeImage := bmp.Width * bmp.Height * 4;
Result := ctx;
finally
jpeg.Free;
end;
end;
function func_close(ih: INPUT_HANDLE): BOOL; cdecl;
var
ctx: PFileContext;
begin
Result := False;
if ih = nil then Exit;
ctx := ih;
ctx^.bitmap.Free;
Dispose(ctx);
Result := True;
end;
function func_info_get(ih: INPUT_HANDLE; info: PInputInfo): BOOL; cdecl;
var
ctx: PFileContext;
begin
Result := False;
if (ih = nil) or (info = nil) then Exit;
ctx := ih;
FillChar(info^, SizeOf(TInputInfo), 0);
info^.flag := INPUT_INFO_FLAG_VIDEO;
info^.rate := 30;
info^.scale := 1;
info^.n := 1; // 静止画1フレーム
info^.format := @ctx^.info;
info^.format_size := SizeOf(BITMAPINFOHEADER);
Result := True;
end;
function func_read_video(ih: INPUT_HANDLE; frame: Integer; buf: Pointer): Integer; cdecl;
var
ctx: PFileContext;
src, dst: PByte;
y, x: Integer;
lineSize: Integer;
c: PRGBQuad;
begin
Result := 0;
if (ih = nil) or (buf = nil) then Exit;
ctx := ih;
lineSize := ctx^.bitmap.Width * 4;
dst := buf;
// biHeight は正(下→上コピー)
for y := ctx^.bitmap.Height - 1 downto 0 do
begin
src := ctx^.bitmap.ScanLine[y];
c := PRGBQuad(src);
for x := 0 to ctx^.bitmap.Width - 1 do
begin
// BGRAのA=255に強制設定
dst^ := c^.rgbBlue; Inc(dst);
dst^ := c^.rgbGreen; Inc(dst);
dst^ := c^.rgbRed; Inc(dst);
dst^ := $FF; Inc(dst); // αチャンネルを255
Inc(c);
end;
end;
Result := ctx^.info.biSizeImage;
end;
function func_read_audio(ih: INPUT_HANDLE; start, length: Integer; buf: Pointer): Integer; cdecl;
begin
Result := 0; // 音声なし
end;
function func_config(hwnd: HWND; hinst: HINST): BOOL; cdecl;
begin
MessageBox(hwnd, 'JPEG Input Plugin (Delphi)', 'AviUtl2InputSample', MB_OK);
Result := True;
end;
var
Plugin: TInputPluginTable = (
flag: INPUT_PLUGIN_FLAG_VIDEO;
name: 'AviUtl2 JPEG Input Sample';
filefilter: 'JPEG File (*.jpg;*.jpeg)'#0'*.jpg;*.jpeg'#0;
information: 'Delphi JPEG Reader for AviUtl2';
func_open: func_open;
func_close: func_close;
func_info_get: func_info_get;
func_read_video: func_read_video;
func_read_audio: func_read_audio;
func_config: func_config;
func_set_track: nil;
func_time_to_frame: nil
);
function GetInputPluginTable: PInputPluginTable; cdecl;
begin
Result := @Plugin;
end;
exports
GetInputPluginTable name 'GetInputPluginTable';
begin
end.
⚙️ ビルド手順
- Delphiでプロジェクトを開く
- 出力フォルダをAviUtl2のPluginsフォルダに指定
- ビルド後、生成された
AviUtl2InputSample.dllを.aui2にリネーム
AviUtl2InputSample.dll → AviUtl2InputSample.aui2
- AviUtl2を起動すると、プラグイン一覧に
「AviUtl2 RGBA JPEG Input Plugin」が表示されます。
🖼️ 実行結果
JPEGファイルをAviUtl2にドラッグ&ドロップすると、
1フレームの静止画オブジェクトが自動生成されます。
💡 コード概要
主要な関数と役割:
| 関数 | 説明 |
|---|---|
func_open |
ファイルを開く(JPEGデコード処理) |
func_info_get |
画像サイズやフォーマット情報をAviUtlに渡す |
func_read_video |
RGBAデータをAviUtlに転送 |
func_read_audio |
非対応(0を返す) |
func_config |
RGB値を変更できる設定ダイアログを表示 |
GetInputPluginTable |
プラグイン情報を登録 |
🚀 応用例
このサンプルを基礎に、以下のような拡張が可能です。
- PSDファイル読み込み(レイヤー合成対応)
- PNG / WebP 対応
- 独自RGBA形式(AI生成画像など)の読み込み
- 画像シーケンスによる動画生成
- αチャンネル(透過)対応
🧑💻 開発者情報
Author: VRAMWiz
Language: Delphi
Platform: Windows 10 / 11
License: MIT License
🔗 関連リンク
- GitHubリポジトリ: https://github.com/vramwiz/AviUtl2InputSample
- AviUtl2公式配布ページ: https://spring-fragrance.mints.ne.jp/aviutl/
📜 ライセンス
このプロジェクトは MIT License のもとで公開されています。
商用・非商用を問わず自由に利用・改変・再配布可能です。
著作権表記とライセンス条文の保持をお願いします。
🎓 DelphiでAviUtl2プラグインを開発できることを実証した、
実用的かつ教育的なサンプルです。
