header={ "chef": "BeatRig", "recipe_version": "1.53", "title": "Convert to ProRes Video", "description": "Convert (almost) any video to an Apple ProRes codec", "spice": "BQ==:G+Hy36kJcnQQYYavb/JV2Il6eCYr6h4hRJHCF9rRbhX5BcazL6cuTgUMdz0xA50VWA5PmmV0Q7aWkiUtNFtbk991l+t0e8IBXMReMIT1GNjnZZDv7n2YRAo0xcSQbY0ixjG6LLH4wGKnspKAoA/v69iLn6N2IH0XzIZwTGdHSo4=", "palette": "Clean Slate", "category": "video", "flavour": "TY1lOWDM8jbvuHTnkKLNGmkXgkRqACvOh7nNmjhZPNTtIfoVGPIhyRLn9pC91xrRozr0L9UQ/Up2IvDhbm8Y/Bqf1rJf2KtXPLDGdKNlLxjNezW7fiuc5lWK8FdaPxMtgcC86X8ubgbgg+wwUub4N/3nKTUBI/A0YQjwygyB2x8=", "time": 1724020825, "core_version": "0.6.4", "magnetron_version": "1.0.317", "dependencies": "ffmpeg,ffprobe", "tags": "ProRes", "os": "windows,macOS", "functions": "main", "uuid": "7ac9517dbb53433683da329326796829", "type": "default", "instructions": "Drop file(s) here" }; // ============================================================================= // GLOBALS var framecount = 0; // ============================================================================= function main() { // MESSAGE setMainMessage("preparing"); // ----------------------------- // CHECK IF FFMPEG AND FFPROBE ARE AVAILABLE if(getAllowedApps("ffmpeg") == '' ) abort("FFMPEG is not available"); if(getAllowedApps("ffprobe") == '' ) abort("FFMPEG is not available"); // ----------------------------- // GET ALL FILES FROM USER INPUT var files = getFiles(); // ----------------------------- // RESET THE META DATA for (i=0;i 0){ ff = concatArray(ff, [ '-map','a:0', '-c:a','pcm_s24le', ]); } // no audio else{ ff = concatArray(ff, [ '-an', ]); } // ff = concatArray(ff, [ '-async','1', '-c:v','prores', '-r','25', '-s','1920x1080', '-aspect','16:9', '-pix_fmt','yuv422p10le', '-profile:v','2', '-vendor','apl0', '-trellis','0', '-subq','7', '-me_range','16', '-b_strategy','1', '-sc_threshold','40', '-qmin','3', '-qmax','51', vidout, '-y', ]); setMainMessage("processing file"); // PROCESSING var ffmpeg = cmd("ffmpeg", ff); // --------------------------------------------------------------------- // THIS FILE IS DONE setProgress(100); setMainMessage("file done"); // SET STATUS files[i]['file_icon'] = "CheckSquare"; files[i]['file_icon_color'] = "FF00aa00"; files[i]['file_status'] = 'DONE'; setFiles(files); // --------------------------------------------------------------------- } // ALL IS DONE setMainMessage("all done"); } // ============================================================================= // FFMPEG PROCESS STATUS // ============================================================================= function cmd_callback(cmd_name, cmd_output){ if(cmd_name=="ffmpeg" && cmd_output.length > 0 && framecount > 0){ var progress = parseInt ( searchRegEx(cmd_output, "(?:frame=)(.*?)(?:fps=)", "i", 1)[0] ); progress = Math.round( progress/framecount* 100 ); setProgress(progress); setMainMessage("processing "+progress+"%"); } } // ============================================================================= // FILE SPECS // ============================================================================= function filespecs(file) { setProgress(101); // ---------------------------------------- // GET VIDEO SPECS var ffprobe = cmd("ffprobe", [ '-v','error', // '-select_streams','v', // '-show_entries','stream=codec_type,codec_name,pix_fmt,width,height,r_frame_rate', "-count_packets", '-show_entries','stream=nb_read_packets,codec_type,pix_fmt,width,height,r_frame_rate,codec_name,channels,sample_rate,bits_per_sample : format=duration', // '-of','default=noprint_wrappers=1', '-i',file ]); var streams = { audio: [], video: [], }; // DURATION var duration = parseFloat ( searchRegEx(ffprobe, "(?:duration=)(.*?)(?=[\n\r])", "i", -1)[0] ); // UGGLY FIX BECAUSE replaceRegEx DOESNT KNOW HOW TO HANDLE NEW LINES ffprobe = replaceRegEx(ffprobe, '[\n\r]', ',', "i"); // EXPLODE INTO STREAMS var ffprobe = searchRegEx(ffprobe, "(?:\\[STREAM\\],)(.*?)(?=,\\[\\/STREAM\\])", "i", -1); // LOOP OVER STREAMS for (var i = 0; i < ffprobe.length; i++) { // EXPLODE ENTRIES var entries = ffprobe[i].split(','); // STREAM DATA var stream = {}; for (var j = 0; j < entries.length; j++) { var l = entries[j].split('='); if ( l[0] == "codec_name" && l[0] != "unknown" ) stream = mergeObject( stream, { "codec_name" : l[1] }); else if ( l[0] == "codec_type" ) stream = mergeObject( stream, { "codec_type" : l[1] }); else if ( l[0] == "sample_rate" ) stream = mergeObject( stream, { "sample_rate" : l[1] }); else if ( l[0] == "channels" ) stream = mergeObject( stream, { "channels" : l[1] }); else if ( l[0] == "bits_per_sample" ) stream = mergeObject( stream, { "bits_per_sample" : l[1] }); else if ( l[0] == "width" ) stream = mergeObject( stream, { "width" : l[1] }); else if ( l[0] == "height" ) stream = mergeObject( stream, { "height" : l[1] }); else if ( l[0] == "pix_fmt" ) stream = mergeObject( stream, { "pix_fmt" : l[1] }); else if ( l[0] == "r_frame_rate" && l[0] != "0/0") stream = mergeObject( stream, { "r_frame_rate" : l[1] }); else if ( l[0] == "nb_read_packets" ) stream = mergeObject( stream, { "nb_read_packets" : l[1] }); } // GROUP AUDIO AND VIDEO STREAMS if( stream.codec_type == "audio") { streams.audio.push(stream); } else if( stream.codec_type == "video") { streams.video.push(stream); } } // get framecount for progress var framecount = (streams.video.length > 0 ? parseInt(streams.video[0].nb_read_packets) : 0); // ---------------------------------------- setProgress(0); return { 'streams' : streams, 'duration' : duration, 'framecount' : framecount }; // ---------------------------------------- }