function LSpinnerShow() { $(".loading-spinner-container").removeClass("d-none"); } function LSpinnerHide() { $(".loading-spinner-container").addClass("d-none"); } // Function to load media data function loadMediaList() { LSpinnerShow(); $("#media-table").addClass("d-none"); const tableBody = $("#media-table tbody"); tableBody.empty(); $.ajax({ url: "/media-list", method: "GET", success: function(data) { if (data.length > 0) { data.forEach((file, index) => { const videoInfo = file.info.video ? file.info.video.map((v, i) => !i ? `<li>Resolution: ${v.resolution}, Codec: ${v.codec}, Bitrate: ${v.bitrate}</li>` : `<li>Resolution: ${v.resolution}, Codec: ${v.codec}</li>`).join("") : "<li>No video streams</li>"; const audioInfo = file.info.audio ? file.info.audio.map(a => `<li>Channels: ${a.layout}, Codec: ${a.codec}, Bitrate: ${a.bitrate}, Language: ${a.language}</li>`).join("") : "<li>No audio streams</li>"; const details = ` <b>Video:</b> <ul>${videoInfo}</ul> <b>Audio:</b> <ul>${audioInfo}</ul> `; const pathEncoded = encodeURIComponent(file.path); tableBody.append(` <tr> <td>${index + 1}</td> <td> <div class="filename"><a href="/single?path=${pathEncoded}"><b>${file.name}</b></a></div> <div class="filepath">${file.path}</div> <div class="filedetails">${details}</div> </td> <td class="size_unit_${file.size_unit}" data-order="${file.size_bytes}">${file.size}${file.size_unit}</td> </tr> `); }); } else { tableBody.append(`<tr><td colspan="3" class="text-center">No files found</td></tr>`); } if(!$('#media-table_wrapper').length) { $('#media-table').DataTable({ columnDefs: [ { targets: "_all", render: function(data, type, row, meta) { var cell = meta.settings.aoData[meta.row].anCells[meta.col]; if (type === 'sort' && cell) { var orderValue = $(cell).attr('data-order'); return orderValue !== undefined ? orderValue : data; } return data; } } ] }); } LSpinnerHide(); $("#media-table").removeClass("d-none"); }, error: function(xhr, status, error) { LSpinnerHide(); console.error("Error loading media list:", error); } }); } function rescanMediaLibHandler() { $("#do-rescan-media-lib").on("click", function(){ $.getJSON("/media-list/clear-cache").done(function(resp){ if(resp.status) { return loadMediaList(); } console.error("Error of rescan media library"); // TODO: make alert bar alert("Error of rescan media library"); }); }); } function transcodateFormHandlers() { const codecCRFMap = { "libx264": [0, 51], "libx265": [0, 51], "libvpx-vp9": [0, 63], "libaom-av1": [0, 63] }; const maxResolution = $(`[name="resolution"]`).data("max-resolution"); $(`[name="resolution"] option`).each(function(){ parseInt($(this).attr("value")) > maxResolution ? $(this).attr("disabled", "disabled") : !$(`[name="resolution"] option[selected]`).length && $(this).attr("selected", "selected") }); $(".show-transcodate-form").on("click", function(){ const formContainer = $(".transcodate-form-container"); if(formContainer.is(":visible")) { formContainer.slideUp(); } else { formContainer.slideDown(); } }); $(".close-transcodate-form-container").on("click", function(){ const formContainer = $(".transcodate-form-container"); formContainer.slideUp(); }); const socket = io(); // Listen for progress updates socket.on("progress", (data) => { document.getElementById("progress").innerText = data.message; }); // Listen for completion socket.on("completed", (data) => { document.getElementById("progress").innerText = "Completed!"; }); // Listen for errors socket.on("error", (data) => { alert(data.message); }); $(".transcodate-form-container .run-transcodate").on("click", async () => { const formContiner = $(".transcodate-form-container"); const fields = formContiner.find("[name]"); const data = {}; for(let field of fields) { field = $(field); data[field.attr("name")] = field.val(); } data["crf"] = "" + Math.abs(data["crf"]); console.log(data); const response = await fetch("/process-media", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }); if (response.ok) { document.getElementById("progress").innerText = "Processing started..."; } else { const error = await response.json(); alert(`Error: ${error.error}`); } }); $("#codec").on("change", function(){ const crf = $(`[name="crf"]`); const codec = $(this).val(); crf.attr("min", codecCRFMap[codec][0]); crf.attr("max", codecCRFMap[codec][1]); if(parseInt(crf.val()) > codecCRFMap[codec][1]) { crf.val(codecCRFMap[codec][1]); } crf.parent().find(".crf-range").text(`${codecCRFMap[codec][0]}-${codecCRFMap[codec][1]}`); // toggle form of preset const presetLibxForm = $(`[name="preset-libx"]`); const presetVP9Form = $(`[name="preset-vp9"]`); const presetAV1Form = $(`[name="preset-av1"]`); if(codec == "libx264" || codec == "libx265") { presetLibxForm.show(); presetVP9Form.hide(); presetAV1Form.hide(); } else if(codec == "libaom-av1"){ presetLibxForm.hide(); presetVP9Form.hide(); presetAV1Form.show(); } else if(codec == "libvpx-vp9") { presetLibxForm.hide(); presetVP9Form.show(); presetAV1Form.hide(); } }); $(`[name="crf"]`).on("input", function(){ const val = parseInt($(this).val()); if(isNaN(val)) { $(this).val(0); return; } if(val < 0) { $(this).val(0); return; } const max = parseInt($(this).attr("max")); if(val > max) { $(this).val(max); } }); } // Load media list when the page is ready $(document).ready(function() { loadMediaList(); rescanMediaLibHandler(); transcodateFormHandlers(); });