178 lines
4.7 KiB
Python
178 lines
4.7 KiB
Python
from django.contrib import admin
|
|
|
|
from .models import MediaAsset, TranscodeJob, TranscodePreset
|
|
|
|
|
|
@admin.register(MediaAsset)
|
|
class MediaAssetAdmin(admin.ModelAdmin):
|
|
list_display = [
|
|
"filename",
|
|
"status",
|
|
"duration_display",
|
|
"resolution",
|
|
"created_at",
|
|
]
|
|
list_filter = ["status", "video_codec", "audio_codec"]
|
|
search_fields = ["filename", "file_path", "comments"]
|
|
readonly_fields = ["id", "created_at", "updated_at", "properties"]
|
|
|
|
fieldsets = [
|
|
(None, {"fields": ["id", "filename", "file_path", "status", "error_message"]}),
|
|
(
|
|
"Media Info",
|
|
{
|
|
"fields": [
|
|
"file_size",
|
|
"duration",
|
|
"video_codec",
|
|
"audio_codec",
|
|
"width",
|
|
"height",
|
|
"framerate",
|
|
"bitrate",
|
|
]
|
|
},
|
|
),
|
|
("Annotations", {"fields": ["comments", "tags"]}),
|
|
(
|
|
"Metadata",
|
|
{
|
|
"classes": ["collapse"],
|
|
"fields": ["properties", "created_at", "updated_at"],
|
|
},
|
|
),
|
|
]
|
|
|
|
def duration_display(self, obj):
|
|
if obj.duration:
|
|
mins, secs = divmod(int(obj.duration), 60)
|
|
hours, mins = divmod(mins, 60)
|
|
if hours:
|
|
return f"{hours}:{mins:02d}:{secs:02d}"
|
|
return f"{mins}:{secs:02d}"
|
|
return "-"
|
|
|
|
duration_display.short_description = "Duration"
|
|
|
|
def resolution(self, obj):
|
|
if obj.width and obj.height:
|
|
return f"{obj.width}x{obj.height}"
|
|
return "-"
|
|
|
|
|
|
@admin.register(TranscodePreset)
|
|
class TranscodePresetAdmin(admin.ModelAdmin):
|
|
list_display = ["name", "container", "video_codec", "audio_codec", "is_builtin"]
|
|
list_filter = ["is_builtin", "container", "video_codec"]
|
|
search_fields = ["name", "description"]
|
|
readonly_fields = ["id", "created_at", "updated_at"]
|
|
|
|
fieldsets = [
|
|
(None, {"fields": ["id", "name", "description", "is_builtin"]}),
|
|
("Output", {"fields": ["container"]}),
|
|
(
|
|
"Video",
|
|
{
|
|
"fields": [
|
|
"video_codec",
|
|
"video_bitrate",
|
|
"video_crf",
|
|
"video_preset",
|
|
"resolution",
|
|
"framerate",
|
|
]
|
|
},
|
|
),
|
|
(
|
|
"Audio",
|
|
{
|
|
"fields": [
|
|
"audio_codec",
|
|
"audio_bitrate",
|
|
"audio_channels",
|
|
"audio_samplerate",
|
|
]
|
|
},
|
|
),
|
|
(
|
|
"Advanced",
|
|
{
|
|
"classes": ["collapse"],
|
|
"fields": ["extra_args", "created_at", "updated_at"],
|
|
},
|
|
),
|
|
]
|
|
|
|
|
|
@admin.register(TranscodeJob)
|
|
class TranscodeJobAdmin(admin.ModelAdmin):
|
|
list_display = [
|
|
"id_short",
|
|
"source_asset_id_short",
|
|
"status",
|
|
"progress_display",
|
|
"created_at",
|
|
]
|
|
list_filter = ["status"]
|
|
search_fields = ["output_filename"]
|
|
readonly_fields = [
|
|
"id",
|
|
"created_at",
|
|
"started_at",
|
|
"completed_at",
|
|
"progress",
|
|
"current_frame",
|
|
"current_time",
|
|
"speed",
|
|
"celery_task_id",
|
|
"preset_snapshot",
|
|
]
|
|
|
|
fieldsets = [
|
|
(None, {"fields": ["id", "source_asset_id", "status", "error_message"]}),
|
|
(
|
|
"Configuration",
|
|
{
|
|
"fields": [
|
|
"preset_id",
|
|
"preset_snapshot",
|
|
"trim_start",
|
|
"trim_end",
|
|
"priority",
|
|
]
|
|
},
|
|
),
|
|
("Output", {"fields": ["output_filename", "output_path", "output_asset_id"]}),
|
|
(
|
|
"Progress",
|
|
{"fields": ["progress", "current_frame", "current_time", "speed"]},
|
|
),
|
|
(
|
|
"Worker",
|
|
{
|
|
"classes": ["collapse"],
|
|
"fields": [
|
|
"celery_task_id",
|
|
"created_at",
|
|
"started_at",
|
|
"completed_at",
|
|
],
|
|
},
|
|
),
|
|
]
|
|
|
|
def id_short(self, obj):
|
|
return str(obj.id)[:8]
|
|
|
|
id_short.short_description = "ID"
|
|
|
|
def source_asset_id_short(self, obj):
|
|
return str(obj.source_asset_id)[:8] if obj.source_asset_id else "-"
|
|
|
|
source_asset_id_short.short_description = "Source"
|
|
|
|
def progress_display(self, obj):
|
|
return f"{obj.progress:.1f}%"
|
|
|
|
progress_display.short_description = "Progress"
|