Added ffmpeg configurable flags and temp storage for encoding. Closes #5
This commit is contained in:
+224
-37
@@ -7,10 +7,10 @@
|
||||
<div class="mb-8">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-white mb-2">Configuration</h1>
|
||||
<p class="text-gray-300">Manage watch folders for video and audio encoding</p>
|
||||
<h1 class="text-4xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-fuchsia-400 via-sky-400 to-cyan-400 mb-2 tracking-tight">Configuration</h1>
|
||||
<p class="text-gray-300 text-lg">Manage watch folders for video and audio encoding</p>
|
||||
</div>
|
||||
<a href="{{ url_for('index') }}" class="bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-lg text-sm">
|
||||
<a href="{{ url_for('index') }}" class="bg-gradient-to-r from-sky-600 to-fuchsia-600 hover:from-sky-500 hover:to-fuchsia-500 text-white px-6 py-2 rounded-full text-base shadow-lg font-semibold transition-all">
|
||||
← Back to Dashboard
|
||||
</a>
|
||||
</div>
|
||||
@@ -18,52 +18,116 @@
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<!-- Video Encoder Configuration -->
|
||||
<div class="bg-gray-800 rounded-lg shadow-lg p-6">
|
||||
<h2 class="text-xl font-semibold text-white mb-4 flex items-center">
|
||||
<svg class="w-6 h-6 mr-2 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<div class="bg-gray-900 rounded-2xl modern-shadow p-8 transition-all hover:scale-[1.01]">
|
||||
<h2 class="text-2xl font-bold text-white mb-4 flex items-center">
|
||||
<svg class="w-7 h-7 mr-2 text-sky-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
Video Encoder Folders
|
||||
</h2>
|
||||
|
||||
<!-- Add new folder form -->
|
||||
<form method="POST" action="{{ url_for('add_config') }}" class="mb-6">
|
||||
<form method="POST" action="{{ url_for('add_config') }}" class="mb-6" id="video-config-form">
|
||||
<input type="hidden" name="encoder_type" value="video">
|
||||
<div class="flex space-x-2">
|
||||
<input type="text" name="watch_folder" placeholder="/path/to/video/folder"
|
||||
class="flex-1 bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent">
|
||||
<button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm font-medium">
|
||||
Add Folder
|
||||
</button>
|
||||
<div class="flex flex-col space-y-2">
|
||||
<div class="flex space-x-2 items-end">
|
||||
<div class="flex-1">
|
||||
<label for="video-folder-picker" class="text-xs text-gray-400 mb-1 block">Watch Folder</label>
|
||||
<div id="video-folder-picker" class="bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-white cursor-pointer select-none" style="min-height:2.5rem;">
|
||||
<span id="video-folder-path">/</span>
|
||||
</div>
|
||||
<input type="hidden" name="watch_folder" id="video-folder-input" value="/">
|
||||
<div id="video-folder-list" class="bg-gray-800 border border-gray-700 rounded-lg mt-1 p-2 text-white text-sm hidden"></div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label for="video-temp-picker" class="text-xs text-gray-400 mb-1 block">Temp Directory</label>
|
||||
<div id="video-temp-picker" class="bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-white cursor-pointer select-none" style="min-height:2.5rem;">
|
||||
<span id="video-temp-path">/temp</span>
|
||||
</div>
|
||||
<input type="hidden" name="temp_dir" id="video-temp-input" value="/temp">
|
||||
<div id="video-temp-list" class="bg-gray-800 border border-gray-700 rounded-lg mt-1 p-2 text-white text-sm hidden"></div>
|
||||
</div>
|
||||
<button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm font-medium">
|
||||
Add Folder
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<div class="flex flex-col">
|
||||
<label for="crf" class="text-xs text-gray-400 mb-1">CRF (Quality)
|
||||
<span title="Constant Rate Factor. Lower is better quality. 18-28 typical. Recommended: 22-28 for H.265." class="ml-1 text-blue-300 cursor-help">?</span>
|
||||
</label>
|
||||
<select name="crf" id="crf" class="bg-gray-700 border border-gray-600 rounded-lg px-2 py-1 text-white">
|
||||
<option value="18">18</option>
|
||||
<option value="20">20</option>
|
||||
<option value="22">22</option>
|
||||
<option value="24" selected>24</option>
|
||||
<option value="26">26</option>
|
||||
<option value="28">28</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label for="preset" class="text-xs text-gray-400 mb-1">Preset
|
||||
<span title="Encoding speed. Slower = better compression. Recommended: medium/slow." class="ml-1 text-blue-300 cursor-help">?</span>
|
||||
</label>
|
||||
<select name="preset" id="preset" class="bg-gray-700 border border-gray-600 rounded-lg px-2 py-1 text-white">
|
||||
<option value="ultrafast">ultrafast</option>
|
||||
<option value="superfast">superfast</option>
|
||||
<option value="veryfast">veryfast</option>
|
||||
<option value="faster">faster</option>
|
||||
<option value="fast">fast</option>
|
||||
<option value="medium" selected>medium</option>
|
||||
<option value="slow">slow</option>
|
||||
<option value="slower">slower</option>
|
||||
<option value="veryslow">veryslow</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Current folders -->
|
||||
<div class="space-y-2">
|
||||
<div class="space-y-3 mt-4">
|
||||
{% if video_configs %}
|
||||
{% for config in video_configs %}
|
||||
<div class="bg-gray-700 rounded-lg p-3 flex items-center justify-between">
|
||||
<div class="bg-gray-800 rounded-xl p-4 flex items-center justify-between modern-shadow transition-all hover:scale-[1.01]">
|
||||
<div>
|
||||
<div class="text-white text-sm">{{ config.watch_folder }}</div>
|
||||
<div class="text-white text-lg font-semibold flex items-center">
|
||||
<svg class="w-4 h-4 mr-1 text-sky-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none" /></svg>
|
||||
{{ config.watch_folder }}
|
||||
</div>
|
||||
<div class="text-gray-400 text-xs">Added: {{ config.created_at.strftime('%Y-%m-%d %H:%M') }}</div>
|
||||
{% if config.temp_dir %}
|
||||
<div class="text-blue-200 text-xs mt-1">Temp Dir: <span class="bg-blue-900 px-1 rounded">{{ config.temp_dir }}</span></div>
|
||||
{% endif %}
|
||||
{% if config.ffmpeg_flags %}
|
||||
{% set flags = config.ffmpeg_flags.split() %}
|
||||
<div class="text-blue-300 text-xs mt-1">
|
||||
<span title="FFmpeg flags used for this folder">
|
||||
Flags:
|
||||
{% for flag in flags %}
|
||||
<span class="bg-blue-900 px-1 rounded mr-1">{{ flag }}</span>
|
||||
{% endfor %}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
{% if config.watch_folder | path_exists %}
|
||||
<span class="w-2 h-2 bg-green-500 rounded-full"></span>
|
||||
<span class="text-green-400 text-xs">Active</span>
|
||||
<span class="text-green-400 text-xs font-semibold">Active</span>
|
||||
{% else %}
|
||||
<span class="w-2 h-2 bg-red-500 rounded-full"></span>
|
||||
<span class="text-red-400 text-xs">Not Found</span>
|
||||
<span class="text-red-400 text-xs font-semibold">Not Found</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="bg-gray-700 rounded-lg p-6 text-center">
|
||||
<div class="bg-gray-800 rounded-xl p-8 text-center modern-shadow">
|
||||
<svg class="mx-auto h-8 w-8 text-gray-400 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z"/>
|
||||
</svg>
|
||||
<p class="text-gray-400 text-sm">No video folders configured</p>
|
||||
<p class="text-gray-400 text-base">No video folders configured</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -81,52 +145,96 @@
|
||||
</div>
|
||||
|
||||
<!-- Audio Encoder Configuration -->
|
||||
<div class="bg-gray-800 rounded-lg shadow-lg p-6">
|
||||
<h2 class="text-xl font-semibold text-white mb-4 flex items-center">
|
||||
<svg class="w-6 h-6 mr-2 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<div class="bg-gray-900 rounded-2xl modern-shadow p-8 transition-all hover:scale-[1.01]">
|
||||
<h2 class="text-2xl font-bold text-white mb-4 flex items-center">
|
||||
<svg class="w-7 h-7 mr-2 text-fuchsia-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3"/>
|
||||
</svg>
|
||||
Audio Encoder Folders
|
||||
</h2>
|
||||
|
||||
<!-- Add new folder form -->
|
||||
<form method="POST" action="{{ url_for('add_config') }}" class="mb-6">
|
||||
<form method="POST" action="{{ url_for('add_config') }}" class="mb-6" id="audio-config-form">
|
||||
<input type="hidden" name="encoder_type" value="audio">
|
||||
<div class="flex space-x-2">
|
||||
<input type="text" name="watch_folder" placeholder="/path/to/audio/folder"
|
||||
class="flex-1 bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent">
|
||||
<button type="submit" class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded-lg text-sm font-medium">
|
||||
Add Folder
|
||||
</button>
|
||||
<div class="flex flex-col space-y-2">
|
||||
<div class="flex space-x-2 items-end">
|
||||
<div class="flex-1">
|
||||
<label for="audio-folder-picker" class="text-xs text-gray-400 mb-1 block">Watch Folder</label>
|
||||
<div id="audio-folder-picker" class="bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-white cursor-pointer select-none" style="min-height:2.5rem;">
|
||||
<span id="audio-folder-path">/</span>
|
||||
</div>
|
||||
<input type="hidden" name="watch_folder" id="audio-folder-input" value="/">
|
||||
<div id="audio-folder-list" class="bg-gray-800 border border-gray-700 rounded-lg mt-1 p-2 text-white text-sm hidden"></div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label for="audio-temp-picker" class="text-xs text-gray-400 mb-1 block">Temp Directory</label>
|
||||
<div id="audio-temp-picker" class="bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-white cursor-pointer select-none" style="min-height:2.5rem;">
|
||||
<span id="audio-temp-path">/temp</span>
|
||||
</div>
|
||||
<input type="hidden" name="temp_dir" id="audio-temp-input" value="/temp">
|
||||
<div id="audio-temp-list" class="bg-gray-800 border border-gray-700 rounded-lg mt-1 p-2 text-white text-sm hidden"></div>
|
||||
</div>
|
||||
<button type="submit" class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded-lg text-sm font-medium">
|
||||
Add Folder
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label for="audio_bitrate" class="text-xs text-gray-400 mb-1">Bitrate
|
||||
<span title="Audio bitrate. Higher = better quality. Recommended: 192k-320k." class="ml-1 text-purple-300 cursor-help">?</span>
|
||||
</label>
|
||||
<select name="audio_bitrate" id="audio_bitrate" class="bg-gray-700 border border-gray-600 rounded-lg px-2 py-1 text-white">
|
||||
<option value="128k">128k</option>
|
||||
<option value="192k">192k</option>
|
||||
<option value="256k">256k</option>
|
||||
<option value="320k" selected>320k</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Current folders -->
|
||||
<div class="space-y-2">
|
||||
<div class="space-y-3 mt-4">
|
||||
{% if audio_configs %}
|
||||
{% for config in audio_configs %}
|
||||
<div class="bg-gray-700 rounded-lg p-3 flex items-center justify-between">
|
||||
<div class="bg-gray-800 rounded-xl p-4 flex items-center justify-between modern-shadow transition-all hover:scale-[1.01]">
|
||||
<div>
|
||||
<div class="text-white text-sm">{{ config.watch_folder }}</div>
|
||||
<div class="text-white text-lg font-semibold flex items-center">
|
||||
<svg class="w-4 h-4 mr-1 text-fuchsia-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none" /></svg>
|
||||
{{ config.watch_folder }}
|
||||
</div>
|
||||
<div class="text-gray-400 text-xs">Added: {{ config.created_at.strftime('%Y-%m-%d %H:%M') }}</div>
|
||||
{% if config.temp_dir %}
|
||||
<div class="text-purple-200 text-xs mt-1">Temp Dir: <span class="bg-purple-900 px-1 rounded">{{ config.temp_dir }}</span></div>
|
||||
{% endif %}
|
||||
{% if config.ffmpeg_flags %}
|
||||
{% set flags = config.ffmpeg_flags.split() %}
|
||||
<div class="text-purple-300 text-xs mt-1">
|
||||
<span title="FFmpeg flags used for this folder">
|
||||
Flags:
|
||||
{% for flag in flags %}
|
||||
<span class="bg-purple-900 px-1 rounded mr-1">{{ flag }}</span>
|
||||
{% endfor %}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
{% if config.watch_folder | path_exists %}
|
||||
<span class="w-2 h-2 bg-green-500 rounded-full"></span>
|
||||
<span class="text-green-400 text-xs">Active</span>
|
||||
<span class="text-green-400 text-xs font-semibold">Active</span>
|
||||
{% else %}
|
||||
<span class="w-2 h-2 bg-red-500 rounded-full"></span>
|
||||
<span class="text-red-400 text-xs">Not Found</span>
|
||||
<span class="text-red-400 text-xs font-semibold">Not Found</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="bg-gray-700 rounded-lg p-6 text-center">
|
||||
<div class="bg-gray-800 rounded-xl p-8 text-center modern-shadow">
|
||||
<svg class="mx-auto h-8 w-8 text-gray-400 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z"/>
|
||||
</svg>
|
||||
<p class="text-gray-400 text-sm">No audio folders configured</p>
|
||||
<p class="text-gray-400 text-base">No audio folders configured</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -144,4 +252,83 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add a section at the bottom for flag explanations -->
|
||||
<div class="mt-10 bg-gray-900 bg-opacity-80 border border-gray-700 rounded-lg p-6">
|
||||
<h3 class="text-lg font-semibold text-white mb-2">FFmpeg Flag Reference</h3>
|
||||
<ul class="text-sm text-gray-300 space-y-1">
|
||||
<li><span class="font-mono text-blue-300">-crf</span>: Constant Rate Factor (quality, lower is better, 18-28 typical, recommended 22-28 for H.265)</li>
|
||||
<li><span class="font-mono text-blue-300">-preset</span>: Encoding speed (ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow; slower = better compression)</li>
|
||||
<li><span class="font-mono text-purple-300">-b:a</span>: Audio bitrate (e.g. 192k, 256k, 320k; higher = better quality, larger file)</li>
|
||||
<li><span class="font-mono text-blue-300">-vf</span>: Video filters (e.g. scale, crop, etc.)</li>
|
||||
<li><span class="font-mono text-blue-300">-c:a</span>: Audio codec (e.g. copy, aac, libmp3lame)</li>
|
||||
<li><span class="font-mono text-blue-300">-c:v</span>: Video codec (e.g. libx265, libx264)</li>
|
||||
</ul>
|
||||
<div class="text-xs text-gray-400 mt-2">Hover over the <span class="font-bold">?</span> icons for more info on each flag.</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
function setupFolderPicker(pickerId, pathId, inputId, listId) {
|
||||
const picker = document.getElementById(pickerId);
|
||||
const pathSpan = document.getElementById(pathId);
|
||||
const input = document.getElementById(inputId);
|
||||
const list = document.getElementById(listId);
|
||||
let currentPath = input.value || '/';
|
||||
function showList(path) {
|
||||
fetch(`/api/list_dir?path=${encodeURIComponent(path)}`)
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
list.innerHTML = `<div class='text-red-400'>${data.error}</div>`;
|
||||
list.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
list.innerHTML = '';
|
||||
if (path !== '/') {
|
||||
const up = document.createElement('div');
|
||||
up.textContent = '.. (up)';
|
||||
up.className = 'cursor-pointer hover:bg-gray-700 px-2 py-1 rounded';
|
||||
up.onclick = () => {
|
||||
const parent = path.replace(/\/$/, '').split('/').slice(0, -1).join('/') || '/';
|
||||
currentPath = parent;
|
||||
pathSpan.textContent = parent;
|
||||
input.value = parent;
|
||||
showList(parent);
|
||||
};
|
||||
list.appendChild(up);
|
||||
}
|
||||
data.dirs.forEach(dir => {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = dir;
|
||||
div.className = 'cursor-pointer hover:bg-gray-700 px-2 py-1 rounded';
|
||||
div.onclick = () => {
|
||||
let newPath = path === '/' ? `/${dir}` : `${path}/${dir}`;
|
||||
currentPath = newPath;
|
||||
pathSpan.textContent = newPath;
|
||||
input.value = newPath;
|
||||
showList(newPath);
|
||||
};
|
||||
list.appendChild(div);
|
||||
});
|
||||
list.classList.remove('hidden');
|
||||
});
|
||||
}
|
||||
picker.onclick = function(e) {
|
||||
e.stopPropagation();
|
||||
showList(currentPath);
|
||||
};
|
||||
document.addEventListener('click', function() {
|
||||
list.classList.add('hidden');
|
||||
});
|
||||
list.onclick = function(e) {
|
||||
e.stopPropagation();
|
||||
};
|
||||
}
|
||||
setupFolderPicker('video-folder-picker', 'video-folder-path', 'video-folder-input', 'video-folder-list');
|
||||
setupFolderPicker('audio-folder-picker', 'audio-folder-path', 'audio-folder-input', 'audio-folder-list');
|
||||
setupFolderPicker('video-temp-picker', 'video-temp-path', 'video-temp-input', 'video-temp-list');
|
||||
setupFolderPicker('audio-temp-picker', 'audio-temp-path', 'audio-temp-input', 'audio-temp-list');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user