ChatGPTはコマンドツールのフロントエンド作成に向いているかもしれない-ffmpegフロントエンド-
コマンドラインツールはその強力さと柔軟性から、データサイエンス、システム管理、ソフトウェア開発など、多くの技術分野で広く利用されています。しかし、その一方で、コマンドを打つことは初心者や非技術者にとっては使いづらいと感じることがあります。そのため、GUI(グラフィカルユーザインターフェース)を持つフロントエンドのみが提供されるツールも数多く存在します。
ffmpegもその一つで動画や音声のあらゆる変換ができますがオプションが多いです。
提供されるフロントエンドも当然機能が多く、どの設定をいじればいいのかわからないこともあります。
しかし、フロントエンドの開発は時間と労力を必要とするため、特定のコマンドラインツールの便利な機能を利用するためだけにGUIを開発するのは割に合いません。ここでChatGPTの出番です。
フロントエンド作成の支援
特定のコマンドラインツールの機能を使う場合、ChatGPTに要件を入力するとそのツールを使用して目的を達成するためのスクリプトを作ってくれます。さらに、ChatGPTはPowerShellやHTAのようなスクリプト言語で「フロントエンドを作成して」といえば簡単なGUIを生成するためのスクリプトを書いてくれます。
これにより、ユーザーはGUIツールを独自に開発する必要なく、ニッチだけど便利なコマンドラインツールの機能をGUI上で簡単に利用できます。Pythonや実行ファイルを作成するよりも手軽に実行できます。
今回はPowerShellスクリプトを使用して、強力なオーディオ変換ツールであるffmpegの簡易GUIを作成しました。ffmpegのみではできない、音声入りPowerPointの音声ファイルのサイズを落とすため(こんな需要あるのか、というのが大事)、
・いったんPowerPointをzipファイルとして解凍
・その中の音声ファイルをサイズ変更
・再度PowerPointに
というPowerShellの力も借りたものを作ってくれ、さらにユーザーインターフェイスも作成できました。
また動画の再生速度を自由に変更するためのHTAアプリケーションも作成してみました。HTAなどは「ボタンをWindows10風にして」といえばWindows10風になるものも面白いです。
作成例
結論
それまで敷居が高く感じていたコマンドラインツールをより手軽に利用できるようになります。PowerShellやHTAなどを使うと特別な環境がなくても実行でき、またコマンドラインツール同士を組み合わせることもできるため自分だけのニッチだけど便利なコマンドラインツールが容易に作成できるとおもいます。
便利になったものです。
文中のツールのコード
聞けば作ってくれますが
音声入りPowerPointの音声のビットレート変更ツール
メモ帳に下記のコードを貼り付けて拡張子.ps1で保存
実行時は右クリックからPowerShellの実行
# Windows Formsアセンブリのロード
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# フォームの作成
$form = New-Object System.Windows.Forms.Form
$form.Text = "PowerPoint 音声変換ツール"
$form.Size = New-Object System.Drawing.Size(600,280)
$form.StartPosition = "CenterScreen"
# 使い方ボタンの作成
$howToUseButton = New-Object System.Windows.Forms.Button
$howToUseButton.Location = New-Object System.Drawing.Size(125,220)
$howToUseButton.Size = New-Object System.Drawing.Size(150,23)
$howToUseButton.Text = "使い方"
$howToUseButton.Add_Click({
[System.Windows.Forms.MessageBox]::Show("1. ビットレートを選択します。`n" +
"2. 'ファイル選択' ボタンをクリックして、変換したい PowerPoint ファイル(.pptx、.ppsx、.pptm)を選択します。`n" +
"3. 'フォルダ選択' ボタンをクリックして、変換後のファイルを保存するフォルダを選択します。`n" +
"4. '変換' ボタンをクリックして変換を開始します。変換が完了すると、ファイルサイズの変化がメッセージボックスで表示されます。`n" +
"注意: このツールは ffmpeg を使用して音声ファイルのビットレートを変換します。ffmpeg のパスは初回実行時に指定し、INIファイルに保存されます。")
})
$form.Controls.Add($howToUseButton)
# ffmpegパス指定ボタンの作成
$ffmpegPathButton = New-Object System.Windows.Forms.Button
$ffmpegPathButton.Location = New-Object System.Drawing.Size(125,190)
$ffmpegPathButton.Size = New-Object System.Drawing.Size(150,23)
$ffmpegPathButton.Text = "ffmpegパス設定"
$ffmpegPathButton.Add_Click({
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.Filter = "EXE files (*.exe)|*.exe"
$OpenFileDialog.Title = "ffmpeg.exeを選択してください"
if($OpenFileDialog.ShowDialog() -eq "OK"){
$ffmpegPath = $OpenFileDialog.FileName
$ffmpegPath | Out-File "ffmpeg_path.ini"
}
})
$form.Controls.Add($ffmpegPathButton)
# ビットレートラベルとコンボボックスの作成
$bitrateLabel = New-Object System.Windows.Forms.Label
$bitrateLabel.Location = New-Object System.Drawing.Size(30,20)
$bitrateLabel.Size = New-Object System.Drawing.Size(70,20)
$bitrateLabel.Text = "ビットレート:"
$form.Controls.Add($bitrateLabel)
$bitrateCombobox = New-Object System.Windows.Forms.ComboBox
$bitrateCombobox.Location = New-Object System.Drawing.Size(100,20)
$bitrateCombobox.Size = New-Object System.Drawing.Size(120,20)
8..320 | ForEach-Object {if ($_ % 8 -eq 0) {$bitrateCombobox.Items.Add($_)}}
$form.Controls.Add($bitrateCombobox)
# サンプルレートラベルとコンボボックスの作成
$sampleRateLabel = New-Object System.Windows.Forms.Label
$sampleRateLabel.Location = New-Object System.Drawing.Size(230,20)
$sampleRateLabel.Size = New-Object System.Drawing.Size(100,20)
$sampleRateLabel.Text = "サンプルレート:"
$form.Controls.Add($sampleRateLabel)
$sampleRateCombobox = New-Object System.Windows.Forms.ComboBox
$sampleRateCombobox.Location = New-Object System.Drawing.Size(330,20)
$sampleRateCombobox.Size = New-Object System.Drawing.Size(120,20)
$sampleRateCombobox.Items.Add(8000)
$sampleRateCombobox.Items.Add(16000)
$sampleRateCombobox.Items.Add(22050)
$sampleRateCombobox.Items.Add(44100)
$sampleRateCombobox.Items.Add(48000)
$form.Controls.Add($sampleRateCombobox)
# PowerPointファイル選択ボタンの作成
$selectPptxButton = New-Object System.Windows.Forms.Button
$selectPptxButton.Location = New-Object System.Drawing.Size(10,50)
$selectPptxButton.Size = New-Object System.Drawing.Size(100,23)
$selectPptxButton.Text = "ファイル選択"
$selectPptxButton.Add_Click({
$openFileDialog.ShowDialog() | Out-Null
$pptxPathTextBox.Text = $openFileDialog.FileName
})
$form.Controls.Add($selectPptxButton)
# PowerPointファイルパステキストボックスの作成
$pptxPathTextBox = New-Object System.Windows.Forms.TextBox
$pptxPathTextBox.Location = New-Object System.Drawing.Size(120,50)
$pptxPathTextBox.Size = New-Object System.Drawing.Size(200,20)
$form.Controls.Add($pptxPathTextBox)
# 出力フォルダ選択ボタンの作成
$selectFolderButton = New-Object System.Windows.Forms.Button
$selectFolderButton.Location = New-Object System.Drawing.Size(10,80)
$selectFolderButton.Size = New-Object System.Drawing.Size(100,23)
$selectFolderButton.Text = "フォルダ選択"
$selectFolderButton.Add_Click({
$folderBrowserDialog.ShowDialog() | Out-Null
$folderPathTextBox.Text = $folderBrowserDialog.SelectedPath
})
$form.Controls.Add($selectFolderButton)
# 出力フォルダパステキストボックスの作成
$folderPathTextBox = New-Object System.Windows.Forms.TextBox
$folderPathTextBox.Location = New-Object System.Drawing.Size(120,80)
$folderPathTextBox.Size = New-Object System.Drawing.Size(200,20)
$form.Controls.Add($folderPathTextBox)
# 変換ボタンの作成
$convertButton = New-Object System.Windows.Forms.Button
$convertButton.Location = New-Object System.Drawing.Size(150,120)
$convertButton.Size = New-Object System.Drawing.Size(100,23)
$convertButton.Text = "変換"
$convertButton.Add_Click({
# 変換コード
$bitrate = "$($bitrateComboBox.SelectedItem)k"
$sampleRate = "$($sampleRateCombobox.SelectedItem)"
$originalPptxPath = $pptxPathTextBox.Text
$originalFileSize = (Get-Item $originalPptxPath).Length / 1MB
$outputFolder = $folderPathTextBox.Text
$tempZipPath = Join-Path $outputFolder "temp.zip"
$tempExtractPath = Join-Path $outputFolder "temp_extract"
$ffmpegPath = Get-Content "ffmpeg_path.ini"
$convertedPptxPath = Join-Path $outputFolder (Get-Item $originalPptxPath).Name
if (-not (Test-Path -Path $ffmpegPath)) {
$ffmpegFileDialog.ShowDialog() | Out-Null
$ffmpegPath = $ffmpegFileDialog.FileName
Set-Content "ffmpeg_path.ini" -Value $ffmpegPath
}
Copy-Item -Path $originalPptxPath -Destination $tempZipPath
Expand-Archive -Path $tempZipPath -DestinationPath $tempExtractPath -Force
if (-not (Test-Path -Path $ffmpegPath)) {
[System.Windows.Forms.MessageBox]::Show("ffmpegが見つかりません: $ffmpegPath")
exit
}
Get-ChildItem -Path $tempExtractPath -Filter "*.m4a" -Recurse | ForEach-Object {
$originalAudioPath = $_.FullName
$convertedAudioPath = $_.FullName.Replace(".m4a", "_converted.m4a")
& $ffmpegPath -i $originalAudioPath -ar $sampleRate -b:a $bitrate $convertedAudioPath
Remove-Item -Path $originalAudioPath
Rename-Item -Path $convertedAudioPath -NewName $originalAudioPath
}
Compress-Archive -Path "$tempExtractPath\*" -DestinationPath $tempZipPath -CompressionLevel Optimal -Force
Rename-Item -Path $tempZipPath -NewName $convertedPptxPath
$convertedFileSize = (Get-Item $convertedPptxPath).Length / 1MB
Remove-Item -Path $tempExtractPath -Recurse -Force
$sizeDifference = [math]::Round($convertedFileSize - $originalFileSize, 2)
[System.Windows.Forms.MessageBox]::Show("変換が完了しました。 ファイルサイズの変化: $sizeDifference MB")
})
$form.Controls.Add($convertButton)
# ファイル選択ダイアログの作成
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Filter = "PowerPoint files (*.pptx, *.ppsx, *.pptm)|*.pptx;*.ppsx;*.pptm"
# フォルダ選択ダイアログの作成
$folderBrowserDialog = New-Object System.Windows.Forms.FolderBrowserDialog
# ffmpegファイル選択ダイアログの作成
$ffmpegFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$ffmpegFileDialog.Filter = "Executable files (*.exe)|*.exe"
# フォームの表示
$form.ShowDialog()
FFMPEGフロントエンド(HTA)
メモ帳に下記のコードを貼り付けて拡張子を.htaで保存
<!DOCTYPE html>
<html>
<head>
<hta:application id="oHTA"
applicationname="FFmpeg Frontend"
border="thin"
borderstyle="normal"
caption="yes"
contextmenu="yes"
icon=""
maximizebutton="yes"
minimizebutton="yes"
navigable="yes"
scroll="auto"
selection="yes"
showintaskbar="yes"
singleinstance="yes"
sysmenu="yes"
version="1.0"
windowstate="normal">
<title>FFmpeg Frontend</title>
<style>
body {
font-family: Segoe UI, Tahoma, Geneva, Verdana, sans-serif;
padding: 20px;
color: #444;
}
h1 {
color: #0078D7;
}
p {
margin-bottom: 5px;
}
input[type="number"], select, input[type="text"] {
width: 100%;
padding: 5px;
margin: 5px 0 20px 0;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
button {
background-color: #0078D7;
color: white;
padding: 10px 20px;
margin: 20px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #0062cc;
}
</style>
<script type="text/javascript">
function checkFFmpeg() {
var shell = new ActiveXObject('WScript.Shell');
try {
var ffmpeg = shell.Exec('ffmpeg -version');
return true;
} catch (e) {
return false;
}
}
function convertVideo() {
var videoFile = document.getElementById('videoFile').value;
var outputFormat = document.getElementById('outputFormat').value;
var frameRate = document.getElementById('frameRate').value;
var bitRate = document.getElementById('bitRate').value;
var width = document.getElementById('width').value;
var height = document.getElementById('height').value;
var speed = document.getElementById('speed').value;
var outputPath = document.getElementById('outputPath').value;
if (outputPath === '') {
outputPath = videoFile.substring(0, videoFile.lastIndexOf("\\"));
}
var outputFileName = videoFile.split('\\').pop().split('/').pop().split('.')[0];
var command = 'ffmpeg -i "' + videoFile + '"';
if (frameRate !== '') {
command += ' -r ' + frameRate;
}
if (bitRate !== '') {
command += ' -b:v ' + bitRate + 'k';
}
if (width !== '' && height !== '') {
command += ' -s ' + width + 'x' + height;
}
if (speed !== '') {
command += ' -filter:v "setpts=' + speed + '*PTS"';
}
command += ' "' + outputPath + '/' + outputFileName + '.' + outputFormat + '"';
var shell = new ActiveXObject('WScript.Shell');
shell.Run(command);
}
window.onload = function() {
if (!checkFFmpeg()) {
alert('ffmpegがシステムのPATHまたは同一ディレクトリに存在しません。ffmpegをインストールまたは配置してから再度試してください。');
}
}
</script>
</head>
<body>
<h1>FFmpeg フロントエンド</h1>
<p>ビデオファイルを選択してください:</p>
<input type="file" id="videoFile">
<p>出力形式を選択してください:</p>
<select id="outputFormat">
<option value="mp4">MP4</option>
<option value="avi">AVI</option>
<option value="mov">MOV</option>
</select>
<p>フレームレート (空白の場合、入力ファイルの設定を使用):</p>
<input type="number" id="frameRate" min="1" max="60">
<p>ビットレート (kbps) (空白の場合、入力ファイルの設定を使用):</p>
<input type="number" id="bitRate" min="1" max="10000">
<p>幅 (空白の場合、入力ファイルの設定を使用):</p>
<input type="number" id="width" min="1" max="1920">
<p>高さ (空白の場合、入力ファイルの設定を使用):</p>
<input type="number" id="height" min="1" max="1080">
<p>スピード (空白の場合、入力ファイルの設定を使用):</p>
<select id="speed">
<option value="">入力ファイルの設定を使用</option>
<option value="0.2">0.2倍速 (5倍のスローモーション)</option>
<option value="0.5">0.5倍速 (2倍のスローモーション)</option>
<option value="1">1倍速 (通常速度)</option>
<option value="2">2倍速 (2倍の高速再生)</option>
<option value="5">5倍速 (5倍の高速再生)</option>
</select>
<p>出力先パス (空白の場合、入力ファイルと同じ場所になります):</p>
<input type="text" id="outputPath" placeholder="例:C:/Users/username/Documents">
<br>
<button onclick="convertVideo()">変換</button>
</body>
</html>