#!/usr/bin/lua -- -*- lua -*- -- -- Copyright (c) 2008 Madcap BV (http://www.madcap.nl) -- All rights reserved. -- -- Permission is granted for use, copying, modification, distribution, -- and distribution of modified versions of this work as long as the -- above copyright notice is included. -- -- needs a patch on ffmpeg/ffmpeg.c: -- --- ffmpeg.c (revision 11006) -- +++ ffmpeg.c (working copy) -- @@ -999,7 +999,7 @@ -- nb_frames_dup, nb_frames_drop); -- -- if (verbose >= 0) -- - fprintf(stderr, "%s \r", buf); -- + fprintf(stderr, "%s \n", buf); -- -- fflush(stderr); -- } local status_file local status_tmp local errors = {} local error_markers = { "^(Error.*)$", "^(%[.*%]Error.*)$", "^(Unknown encoder.*)$", "(.*unrecognized option.*)", "(.*no such file or directory.*)", "(.*Unknown format.*)", "(.*Could not find codec parameters.*)", "(.*Assertion.*failed.*)", "(.*Segmentation fault.*)" } function write_status_file(status) local fd = io.open(status_tmp, "w") for k,v in pairs(status) do if k ~= "body" then fd:write(k .. ": " .. v .. "\n") end end if status.body then fd:write("\n" .. status.body .. "\n") end fd:close() os.execute("mv " .. status_tmp .. " " .. status_file) end function transcode(source_path, destination_path, hash, dst_ext, params) local duration = 0 local command = string.format("ffmpeg -i %s/%s/%s %s -y %s/%s.%s 2>&1 &", source_path, string.sub(hash, 1, 1), hash, params, destination_path, hash, dst_ext) local fd = io.popen(command, "r") local line = fd:read("*l") local log = {} local output_seen = false while line do log[#log+1] = line if string.match(line, "^Output #0") then output_seen = true end local patt = string.match(line, "Duration: (.-),") if patt then local match_h, match_m, match_s = string.match(patt, "(%d+):(%d+):(.*)") local h, m, s = tonumber(match_h), tonumber(match_m), tonumber(match_s) if h and m and s then duration = h * 3600 + m * 60 + s else duration = 1 end end local frame = string.match(line, "^frame=.-time=(.-) bitrate") if frame then write_status_file({ Status = "transcoding", Progress = string.format("%.3f", frame / duration) }) end for _,marker in pairs(error_markers) do local error = string.match(line, marker) if error then table.insert(errors, error) end end line = fd:read("*l") end fd:close() if next(errors) ~= nil then fd = io.open(status_file, "w") fd:write("Status: error\n") for _,e in pairs(errors) do fd:write("Errors: " .. e .. "\n") end fd:write("\nffmpeg-output: " .. table.concat(log, "}-{") .. "\n") fd:close() else write_status_file({ Status = "done", Progress = "1.000", Errors = "none", Warnings = "none", ffmpeg-output = table.concat(log, "}-{") }) end end local source_path = arg[1] local hash = arg[2] local dst_ext = arg[3] or "avi" local params = arg[4] or "" if source_path == nil or hash == nil then print("Usage: vpx-transcode BASE_PATH HASH [extension] [\"ffmpeg parameters\"]") os.exit(1) end local destination_path = source_path .. "/transcode" status_file = destination_path .. "/" .. hash .. ".status" status_tmp = destination_path .. "/" .. hash .. ".status.tmp" transcode(source_path, destination_path, hash, dst_ext, params)