header={ "chef": "BeatRig", "recipe_version": "1.28", "title": "Convert To FLAC", "description": "Convert almost any file to FLAC", "spice": "BQ==:G+Hy36kJcnQQYYavb/JV2Il6eCYr6h4hRJHCF9rRbhX5BcazL6cuTgUMdz0xA50VWA5PmmV0Q7aWkiUtNFtbk991l+t0e8IBXMReMIT1GNjnZZDv7n2YRAo0xcSQbY0ixjG6LLH4wGKnspKAoA/v69iLn6N2IH0XzIZwTGdHSo4=", "flavour": "rUU1l8Iq4Gn8e7mccHAW9rTIrkK22PunV7OVZ81XY2QP0HigM56PwxlL5MlI/gDiGVH0J59RK5MXU83NnWMIDrdVCR4Bt1q7QrC77QaSxNx79hrMOMj0dzt/4ZniKy48px/rkrM9YXGI21DryAus9rzSCfllsHDTZBcJO5wYq2o=", "time": 1736285802, "magnetron_version": "1.0.333", "tags": "audio", "core_version": "0.7.2", "palette": "Clean Slate", "dependencies": "ffmpeg,ffprobe", "type": "default", "os": "windows,macOS", "functions": "main", "uuid": "67a5626be28f42e9822814d348a5c8db", "instructions": "Drop file(s) here" }; // ============================================================================= // GLOBALS // ============================================================================= // DURATION OF THE FILE FOR PROGRESS var curDuration = 0; // GLOBAL TO INDICATE IF FFMPEG CAN HANDLE LIBSOXR RESAMPLING var libsoxr = "NOTDEFINED"; // ============================================================================= // MAIN // ============================================================================= function main() { // CHECK IF FFMPEG AND FFPROBE ARE AVAILABLE if(getAllowedApps("ffmpeg") == '' ) abort("FFMPEG is not available"); if(getAllowedApps("ffprobe") == '' ) abort("FFMPEG is not available"); // START PROGRESS setProgress(101); // GET ALL FILES FROM THE APP var files = getFiles(); if( files.length == 0) abort("Add some files first!"); // CLEAN UP THE FILE LIST files.forEach(file => { Object.assign(file, { file_icon: "square", file_icon_color: "FFdddddd", file_status: "", file_tooltip: "", group: "" }); }); setFiles(files); // START PATH var startpath = getPathInfo(files[0].path); // ------------------------------------ var r = openDialog(startpath.folder); // IF CANCELLED if(r.cancel == 1) return; // ------------------------------------ var samplerate = (r.samplerate != "source" ? parseInt(parseFloat(r.samplerate)*1000) : false); var bitrate = (r.bitrate != "source" ? parseInt( r.bitrate) : false) ; // ------------------------------------ for (i=0;i 0 && curDuration > 0) { const progress = Math.round((parseInt(cmd_output.match(/out_time_us=(\d+)/)?.pop() || 0, 10) / 1000000) / curDuration * 100); setProgress(progress); } return { "terminate": isCanceled(), "input": "" }; } // ============================================================================= // OPEN DIALOG // ============================================================================= function openDialog(startfolder) { var form = { // PATH "path_label" : { "type" : "text", "label" : "source folder", "just" : "l", "bounds" : { "x": 20, "w" : 160, }, }, "path_toggle": { "type": "togglebox", "bounds" : { "y": -1, "x": 180, "w" : 25, }, "label" : "", "toggle" : true }, "custompath_label" : { "type" : "text", "label" : "folder", "just" : "l", "bounds" : { "x": 20, "w" : 160, }, "visible": false, }, "custompath" : { "type" : "fileselect", "path" : startfolder, "editable" : false, "dir" : true, "saving" : true, "label" : "empty", "bounds" : { "y": -1, "x": 180, "w" : 340, }, "visible": false, }, // MODE "bitrate_label" : { "type" : "text", "label" : "bitrate", "just" : "l", "bounds" : { "y": 220, "x": 20, "w" : 160, }, }, "bitrate" : { "type" : "combobox", "default" : "source", "items" : "source,32,24,20,16,12,8", "label" : "", "bounds" : { "y": 220, "x" : 180, "w" : 340 }, "visible" : true, }, // SAMPLE RATE "samplerate_label" : { "type" : "text", "label" : "samplerate", "just" : "l", "bounds" : { "y": 260, "x" : 20, "w" : 120 }, }, "samplerate" : { "type" : "combobox", "default" : "source", "items" : "source,192kHz,176.4kHz,96kHz,88.2kHz,48kHz,44.1kHz,32kHz,22.05kHz", "label" : " ", "bounds" : {"y": 260, "x" : 180, "w" : 340 }, }, // COMPRESSION "compression_label" : { "type" : "text", "label" : "compression", "just" : "l", "bounds" : { "x" : 20, "w" : 120 }, }, "compression" : { "type" : "combobox", "default" : "5", "items" : "0,1,2,3,4,5,6,7,8,9,10,11,12", "label" : " ", "bounds" : {"y": -1, "x" : 180, "w" : 340 }, }, // BUTTONS "spacer1" : { "type" : "text", "label" : " ", "just" : "r", "bounds" : { "x": 120, "w" : 200, "h" : 100 }, }, "cancel" : { "type" : "button", "label" : "cancel", "bounds" : { "x": 310, "w" : 100 }, "returns" : 0 }, "go" : { "type" : "button", "label" : "go", "bounds" : { "y": -1, "x": 420, "w" : 100, }, "returns" : 1 } }; return dialog(header.title, "", "", form); } // ============================================================================= function dialog_callback(props) { if (props["name"] == "path_toggle") var r = dialog({ "custompath" : { "visible" : !props["toggle"] }, "custompath_label" : { "visible" : !props["toggle"] } }); } // ============================================================================= // FILE SPECS function filespecs(file) { // FFPROBE COMMAND const ffprobe = cmd("ffprobe", [ "-v", "error", "-print_format", "json", "-show_entries", "stream=codec_type,codec_name,bit_rate,channels,sample_rate,bits_per_sample", "-show_entries", "format=duration,size", "-i", file, ]); // Parse JSON output const specs = JSON.parse(ffprobe); // Extract audio stream information const audioStream = (specs.streams || []).find(stream => stream.codec_type === "audio"); // If there is only one stream, return the audio stream information if( specs.streams.length == 1 && audioStream) { return { codec_name: audioStream?.codec_name || null, channels: parseInt(audioStream?.channels) || 0 , sample_rate: parseInt(audioStream?.sample_rate) || 0, duration: parseFloat(specs.format?.duration) || 0, bits_per_sample: parseInt(audioStream?.bits_per_sample) || 0, bitrate: parseInt(audioStream?.bit_rate) || 0, filesize: parseInt(specs.format?.size) || 0, }; } else { return false; } } // =============================================================================