require 'streamio-ffmpeg' require 'os' module FFMPEG class Screenrecorder attr_reader :opts, :output, :process_id def initialize(opts = {}) @opts = default_config.merge opts @output = opts[:output] @video_file = nil @process_id = nil init_logger(opts[:logging_level]) end def opts=(new_opts) @opts = default_config.merge new_opts @output = opts[:output] init_logger(opts[:logging_level]) if FFMPEG.logger.level != opts[:logging_level] end def start FFMPEG.logger.debug "Starting: #{command}" @video_file = nil # New file @process_id = start_ffmpeg FFMPEG.logger.info 'Recording...' @process_id end def stop FFMPEG.logger.debug 'Stopping ffmpeg.exe...' # msg = Process.kill('INT', @process_id) # Process.detach(@process_id) msg = kill_ffmpeg FFMPEG.logger.debug msg FFMPEG.logger.debug 'Stopped ffmpeg.exe' FFMPEG.logger.info 'Recording complete.' msg end # def inputs(application) # FFMPEG.logger.debug "Retrieving available windows from: #{application}" # available_inputs_by application # end def video_file @video_file ||= Movie.new(output) end private def default_config { input: 'desktop', framerate: 15, device: 'gdigrab', log: 'ffmpeg_recorder_log.txt' } end def start_ffmpeg spawn(command) pid = `powershell (Get-Process ffmpeg).id`.to_i raise 'ffmpeg failed to start.' if pid.zero? pid end def kill_ffmpeg `TASKKILL /f /im ffmpeg.exe` end def init_logger(level) FFMPEG.logger.progname = 'FFMPEG::Recorder' FFMPEG.logger.level = level FFMPEG.logger.formatter = proc do |severity, time, progname, msg| "#{time.strftime('%F %T')} #{progname} - #{severity} - #{msg}\n" end FFMPEG.logger.debug "Logger initialized." end def command "#{FFMPEG.ffmpeg_binary} -y " \ "#{extra_opts}" \ "-f #{opts[:device]} " \ "-framerate #{opts[:framerate]} " \ "-i #{opts[:input]} " \ "#{opts[:output]} " \ "2> #{opts[:log]}" end def extra_opts return nil unless opts[:extra_opts] raise ':extra_opts cannot be empty.' if opts[:extra_opts].empty? arr = [] opts[:extra_opts].each { |k, v| arr.push "-#{k} #{v}" } ' ' + arr.join(' ') + ' ' end # def available_inputs_by(application) # `tasklist /v /fi "imagename eq #{application}.exe" /fo list | findstr Window` # .split("\n") # .reject { |title| title == 'Window Title: N/A' } # end # # def input # return opts[:input] if opts[:input] == 'desktop' # %Q(title="#{opts[:input].gsub('Window Title: ', '')}") # end end # class Recorder end # module FFMPEG