def HasAudio(self, videoPath): """ Check if video have Metadata or not """ try: p = _spawn([ '-i', videoPath, '-show_streams', '-select_streams', 'a', '-preset', 'ultrafast', '-loglevel', 'error' ], t="probe") stdout_data, _ = p.communicate() if stdout_data == b'': qgsu.showUserAndLogMessage( QCoreApplication.translate( "QgsFmvPlayer", "This video doesn't have Audio ! ")) self.actionAudio.setEnabled(False) self.actionSave_Audio.setEnabled(False) return False return True except Exception as e: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Audio check Failed! : "), str(e)) self.actionAudio.setEnabled(False) self.actionSave_Audio.setEnabled(False)
def RecordVideo(self, value): ''' Cut Video ''' currentTime = _seconds_to_time(self.currentInfo) if value is False: self.endRecord = currentTime _, file_extension = os.path.splitext(self.fileName) out, _ = askForFiles(self, QCoreApplication.translate( "QgsFmvPlayer", "Save video record"), isSave=True, exts=file_extension[1:]) if not out: self.StopRecordAnimation() return p = _spawn([ '-i', self.fileName, '-ss', self.startRecord, '-to', self.endRecord, '-preset', 'ultrafast', '-c', 'copy', out ]) p.communicate() qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Save file succesfully!")) self.StopRecordAnimation() else: self.startRecord = currentTime self.RecGIF.frameChanged.connect(self.ReciconUpdate) self.RecGIF.start() return
def probeToJson(self, fname, Output=None): """ Save video data in json format """ p = _spawn([ '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', fname, '>', Output ], t="probe") p.communicate() return
def probeToJson(self, fname, Output=None): p = _spawn(['-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', fname, '>', Output], type="probe") p.communicate() return
def probeGetJson(self, fname, Output=None): p = _spawn(['-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', fname], type="probe") (output, err) = p.communicate() p_status = p.wait() return output
def RecordVideoTask(self, task, infile, startRecord, endRecord, out): ''' Record Video Task ''' p = _spawn([ '-i', infile, '-ss', startRecord, '-to', endRecord, '-c', 'copy', out ]) p.communicate() self.StopRecordAnimation() if task.isCanceled(): return None return {'task': task.description()}
def probeGetJson(self, fname): """ Show json info in table """ p = _spawn(['-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', fname], t="probe") (output, _) = p.communicate() p.wait() return output
def probeToJson(self, fname, Output=None): """ Save video data in json format """ p = _spawn( [ "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", fname, ">", Output, ], t="probe", ) p.communicate() return
def probeGetJson(self, fname): """ Show json info in table """ p = _spawn( [ "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", fname, ], t="probe", ) (output, _) = p.communicate() p.wait() return output
def probe(self, fname, posters_as_video=True): """ Examine the media file and determine its format and media streams. Returns the MediaInfo object, or None if the specified file is not a valid media file. >>> info = FFMpeg().probe('test1.ogg') >>> info.format 'ogg' >>> info.duration 33.00 >>> info.video.codec 'theora' >>> info.video.width 720 >>> info.video.height 400 >>> info.audio.codec 'vorbis' >>> info.audio.channels 2 :param posters_as_video: Take poster images (mainly for audio files) as A video stream, defaults to True """ if not os.path.exists(fname): return None info = MediaInfo(posters_as_video) p = _spawn( ['-preset', 'ultrafast', '-show_format', '-show_streams', fname], t="probe") stdout_data, _ = p.communicate() stdout_data = stdout_data.decode(console_encoding) info.parse_ffprobe(stdout_data) if not info.format.format and len(info.streams) == 0: return None return info
def HasMetadata(self, videoPath): """ Check if video have Metadata or not """ try: p = _spawn([ '-i', videoPath, '-map', 'data-re', '-codec', 'copy', '-f', 'data', '-' ]) stdout_data, _ = p.communicate() if stdout_data == b'': qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "This video don't have Metadata ! : "), level=QGis.Info) return False return True except Exception as e: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "Metadata Callback Failed! : "), str(e), level=QGis.Info)
def HasAudio(self, videoPath): """ Check if video have Metadata or not """ try: p = _spawn([ '-i', videoPath, '-show_streams', '-select_streams', 'a', '-loglevel', 'error' ], type="ffprobe") stdout_data, _ = p.communicate() if stdout_data == b'': qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "This video don't have Audio ! : "), level=QGis.Info) return False return True except Exception as e: qgsu.showUserAndLogMessage(QCoreApplication.translate( "QgsFmvPlayer", "Audio check Failed! : "), str(e), level=QGis.Info)
def RecordVideo(self, value): ''' Cut Video ''' currentTime = _seconds_to_time(self.currentInfo) if value is False: self.endRecord = currentTime _, file_extension = os.path.splitext(self.fileName) out, _ = QFileDialog.getSaveFileName(self, "Save As", "", file_extension) if not out: self.RecGIF.frameChanged.disconnect(self.ReciconUpdate) self.RecGIF.stop() self.btn_Rec.setIcon(QIcon(":/imgFMV/images/record.png")) return False lfn = out.lower() if not lfn.endswith((file_extension)): out += file_extension p = _spawn([ '-i', self.fileName, '-ss', self.startRecord, '-to', self.endRecord, '-c', 'copy', out ]) p.communicate() qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvPlayer", "Save file succesfully!")) self.RecGIF.frameChanged.disconnect(self.ReciconUpdate) self.RecGIF.stop() self.btn_Rec.setIcon(QIcon(":/imgFMV/images/record.png")) else: self.startRecord = currentTime self.RecGIF.frameChanged.connect(self.ReciconUpdate) self.RecGIF.start() return
def convert(self, infile, outfile, opts, timeout=10): """ Convert the source media (infile) according to specified options (a list of ffmpeg switches as strings) and save it to outfile. Convert returns a generator that needs to be iterated to drive the conversion process. The generator will periodically yield timecode of currently processed part of the file (ie. at which second in the content is the conversion process currently). The optional timeout argument specifies how long should the operation be blocked in case ffmpeg gets stuck and doesn't report back. See the documentation in Converter.convert() for more details about this option. >>> conv = FFMpeg().convert('test.ogg', '/tmp/output.mp3', ... ['-acodec libmp3lame', '-vn']) >>> for timecode in conv: ... pass # can be used to inform the user about conversion progress """ if not os.path.exists(infile): raise FFMpegError("Input file doesn't exist: " + infile) cmds = ['-i', infile] cmds.extend(opts) cmds.extend(['-y', outfile]) if windows: timeout = None if timeout: raise Exception('timed out while waiting for ffmpeg') try: p = _spawn(cmds) except OSError: raise FFMpegError('Error while calling ffmpeg binary') yielded = False buf = '' total_output = '' pat = re.compile(r'time=([0-9.:]+) ') while True: if timeout: raise ret = p.stderr.read(10) if timeout: raise if not ret: break ret = ret.decode(console_encoding) total_output += ret buf += ret if '\r' in buf: line, buf = buf.split('\r', 1) tmp = pat.findall(line) if len(tmp) == 1: timespec = tmp[0] if ':' in timespec: timecode = 0 for part in timespec.split(':'): timecode = 60 * timecode + float(part) else: timecode = float(tmp[0]) yielded = True yield timecode if timeout: raise p.communicate() # wait for process to exit if total_output == '': raise FFMpegError('Error while calling ffmpeg binary') cmd = ' '.join(cmds) if '\n' in total_output: line = total_output.split('\n')[-2] if line.startswith('Received signal'): # Received signal 15: terminating. raise FFMpegConvertError(line.split( ':')[0], cmd, total_output, pid=p.pid) if line.startswith(infile + ': '): err = line[len(infile) + 2:] raise FFMpegConvertError('Encoding error', cmd, total_output, err, pid=p.pid) if line.startswith('Error while '): raise FFMpegConvertError('Encoding error', cmd, total_output, line, pid=p.pid) if not yielded: raise FFMpegConvertError('Unknown ffmpeg error', cmd, total_output, line, pid=p.pid) if p.returncode != 0: raise FFMpegConvertError('Exited with code %d' % p.returncode, cmd, total_output, pid=p.pid)
def CreatePlot(self, task, fileName, output, t): """ Create Plot Bitrate Slot""" try: task.setProgress(10) frame_rate = None frame_time = 0.0 # set ffprobe stream specifier if t == 'audio': stream_spec = 'a' elif t == 'video': stream_spec = 'V' else: task.cancel() return None # get frame data for the selected stream cmds = ["-show_entries", "frame", "-select_streams", stream_spec, "-print_format", "xml", fileName] try: with _spawn(cmds, t="probe") as proc_frame: # process xml elements as they close for event in etree.iterparse(proc_frame.stdout): # skip non-frame elements node = event[1] if node.tag != 'frame': continue # count number of frames self.frame_count += 1 # get type of frame if t == 'audio': frame_type = 'A' # pseudo frame type else: frame_type = node.get('pict_type') # get frame rate only once if frame_rate is None: # audio frame rate, 1 / frame duration if t == 'audio': frame_rate = 1.0 / \ float(node.get('pkt_duration_time')) # video frame rate, read stream header else: cmds = ["-show_entries", "stream", "-select_streams", "V", "-print_format", "xml", fileName ] with _spawn(cmds, t="probe") as proc_stream: # parse stream header xml stream_data = etree.parse( proc_stream.stdout) stream_elem = stream_data.find('.//stream') # compute frame rate from ratio frame_rate_ratio = stream_elem.get( 'avg_frame_rate') (dividend, divisor) = frame_rate_ratio.split('/') frame_rate = float( dividend) / float(divisor) # collect frame data try: frame_time = float( node.get('best_effort_timestamp_time')) except Exception: try: frame_time = float(node.get('pkt_pts_time')) except Exception: if self.frame_count > 1: frame_time += float(node.get('pkt_duration_time')) frame_bitrate = (float(node.get('pkt_size')) * 8 / 1000) * frame_rate frame = (frame_time, frame_bitrate) # create new frame list if new type if frame_type not in self.bitrate_data: self.bitrate_data[frame_type] = [] # append frame to list by type self.bitrate_data[frame_type].append(frame) task.setProgress(45) # check if ffprobe was successful if self.frame_count == 0: task.cancel() return None except Exception: task.cancel() return None # end frame subprocess task.setProgress(80) self.output = output if task.isCanceled(): return None return {'task': task.description()} except Exception: task.cancel() return None
def run(self): # qgsu.showUserAndLogMessage("", "callBackMetadataThread run: commands:" + str(self.cmds), onlyLog=True) self.p = _spawn(self.cmds) # print (self.cmds) self.stdout, _ = self.p.communicate()
def CreatePlot(self, file, output, t): """ Create Plot Bitrate Slot""" try: self.progress.emit(10) bitrate_data = {} frame_count = 0 frame_rate = None frame_time = 0.0 # set ffprobe stream specifier if t == 'audio': stream_spec = 'a' elif t == 'video': stream_spec = 'V' else: self.error.emit("CreatePlotsBitrate", "Invalid stream type", traceback.format_exc()) return # get frame data for the selected stream cmds = [ "-show_entries", "frame", "-select_streams", stream_spec, "-print_format", "xml", "-preset", "ultrafast", file ] try: with _spawn(cmds, t="probe") as proc_frame: self.progress.emit(22) # process xml elements as they close for event in etree.iterparse(proc_frame.stdout): self.progress.emit(40) # skip non-frame elements node = event[1] if node.tag != 'frame': continue # count number of frames frame_count += 1 # get type of frame if t == 'audio': frame_type = 'A' # pseudo frame type else: frame_type = node.get('pict_type') # get frame rate only once if frame_rate is None: # audio frame rate, 1 / frame duration if t == 'audio': frame_rate = 1.0 / \ float(node.get('pkt_duration_time')) # video frame rate, read stream header else: cmds = [ "-show_entries", "stream", "-select_streams", "V", "-print_format", "xml", "-preset", "ultrafast", file ] with _spawn(cmds, t="probe") as proc_stream: # parse stream header xml stream_data = etree.parse( proc_stream.stdout) stream_elem = stream_data.find('.//stream') # compute frame rate from ratio frame_rate_ratio = stream_elem.get( 'avg_frame_rate') (dividend, divisor) = frame_rate_ratio.split('/') frame_rate = float(dividend) / float( divisor) # collect frame data try: frame_time = float( node.get('best_effort_timestamp_time')) except: try: frame_time = float(node.get('pkt_pts_time')) except: if frame_count > 1: frame_time += float( node.get('pkt_duration_time')) frame_bitrate = (float(node.get('pkt_size')) * 8 / 1000) * frame_rate frame = (frame_time, frame_bitrate) # create new frame list if new type if frame_type not in bitrate_data: bitrate_data[frame_type] = [] # append frame to list by type bitrate_data[frame_type].append(frame) self.progress.emit(45) # check if ffprobe was successful if frame_count == 0: self.error.emit( "CreatePlotsBitrate", "Error: No frame data, failed to execute ffprobe", traceback.format_exc()) return except: self.error.emit( "CreatePlotsBitrate", "Error: No frame data, failed to execute ffprobe", traceback.format_exc()) return # end frame subprocess self.progress.emit(80) self.return_fig.emit(bitrate_data, frame_count, output) self.finished.emit("CreatePlotsBitrate", "Bitrate correct Finished!") return except Exception as e: self.error.emit("CreatePlotsBitrate", e, traceback.format_exc()) return