def probe(self, path): """Reads stream info from self.filename in 'path' using FFprobe. Args: path (str): directory that self.filename should be searched for Returns: bool: True if successful, False otherwise. """ probe = ffmpy.FFprobe( executable=FFPROBE_PATH, global_options='-show_streams -of json', inputs={os.path.join(path, self.filename): ''} ) try: out, err = probe.run( stdout=subprocess.PIPE, stderr=subprocess.PIPE ) except ffmpy.FFRuntimeError: return False self.info = json.loads(out)['streams'][0] return True
def getMdeiaInof(path): tup_resp = ffmpy.FFprobe( inputs={path: None}, global_options=['-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams']).run( stdout=subprocess.PIPE) meta = json.loads(tup_resp[0].decode('utf-8')) return meta
def split_file(input_file: Path, tracks: List[Track], destination: Path, output_format: str): duration_command = ffmpy.FFprobe(inputs={ str(input_file): '-show_entries format=duration -v quiet -of csv="p=0"' }) stdout, _ = duration_command.run(stdout=subprocess.PIPE) file_duration = float(stdout.decode().strip()) outputs: Dict[Path, str] = {} for i, track in enumerate(tracks): start_timestamp = track.start_timestamp end_timestamp = file_duration if i == len(tracks) - 1 else tracks[ i + 1].start_timestamp outputs[destination / (f"{track.title}.{output_format}" )] = f"-vn -c copy -ss {start_timestamp} -to {end_timestamp}" split_command = ffmpy.FFmpeg( inputs={str(input_file): "-y -hide_banner -loglevel error -stats"}, outputs={str(path): v for path, v in outputs.items()}) try: split_command.run() except: raise Exception( "Something went wrong with the splitting procedure. See the error above." ) from None return list(outputs.keys())
def get_in_codec(file: str) -> str: """ return the audio codec name of file :param file: str file name :return: str codex name """ # https://github.com/Ch00k/ffmpy/blob/master/docs/examples.rst p_command = "-v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1" probe = ffmpy.FFprobe(inputs={file: p_command}) return (probe.run(stdout=subprocess.PIPE))[0].strip()
def get_video_meta_data(filename: str): ff = ffmpy.FFprobe( inputs={filename: None}, global_options=[ '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams']).run(stdout=subprocess.PIPE) meta = json.loads(ff[0].decode('utf-8')) return meta
def get_in_bit_rate(file: str) -> int: """ Returns the bitrate of file with help of ffprobe :param file: str filename :return: int bit rate """ p_command: str = "-v error -select_streams a:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1" probe = ffmpy.FFprobe(inputs={file: p_command}) try: bit_rate = int((probe.run(stdout=subprocess.PIPE))[0]) except ValueError: bit_rate = -1 return bit_rate
def get_video_details(input_file): tup_resp = ffmpy.FFprobe(inputs={ input_file: None }, global_options=[ '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams' ]).run(stdout=subprocess.PIPE) meta = json.loads(tup_resp[0].decode('utf-8')) return meta['streams'][0]
def probe_video(filename: Union[str, Path], input_opts: List[str], verbose: bool = True) -> Tuple[bytes, bytes]: src_path = str(filename) if not verbose: input_opts.append('-v') input_opts.append('quiet') # ffprobe arguments inputs = {src_path: input_opts} ff = ffmpy.FFprobe(inputs=inputs) if verbose: print(f'ffprobe cmd: {ff.cmd}') stdout, stderr = ff.run(stdout=subprocess.PIPE) return stdout, stderr
def _get_ffprobe(file: str, command: str) -> tp.Any: """ Returns the bitrate of file with help of ffprobe :param file: str, filename :param command: str, command for probing :return: retrieved value from probe """ probe = ffmpy.FFprobe(inputs={file: command}) try: query = probe.run(stdout=subprocess.PIPE, stderr=subprocess.PIPE) except ffmpy.FFRuntimeError: return None except ffmpy.FFExecutableNotFoundError: return None else: return query[0]
def get_duration(video_file: str) -> float: # Uses ffprobe to query a file for its duration. (stdout, _stderr) = ffmpy.FFprobe(inputs={ video_file: None }, global_options=[ '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams' ]).run(stdout=subprocess.PIPE) meta = json.loads(stdout.decode('utf-8')) duration = float(meta["format"]["duration"]) log.debug("Duration of %s: %f", video_file, duration) return duration
def main(): # Globals in Python are global to a module, not across all modules. # global validDatesDict # global stripDates # TODO: use command line parameters to determine path to scan # https://stackabuse.com/command-line-arguments-in-python/ parser = argparse.ArgumentParser(description='checkmetadata') # parser.add_argument('-i','--input', help='Input file name', required=True) # generic directory scanning operations - into internal dictionary tree data structure parser.add_argument('-i', '--input', help='Input file name') args = parser.parse_args() print("Input file: %s" % args.input) # ffprobe = ffmpy.FFprobe(global_options="-loglevel quiet -sexagesimal -of json -show_entries stream=width,height,duration -show_entries format=duration -select_streams v:0", inputs={args.input : None}) ffprobe = ffmpy.FFprobe(global_options="-show_format -of json", inputs={args.input: None}) print("ffprobe.cmd:", ffprobe.cmd) # printout the resulting ffprobe shell command stdout, stderr = ffprobe.run(stderr=subprocess.PIPE, stdout=subprocess.PIPE) # std* is byte sequence, but json in Python 3.5.2 requires str ff0string = str(stdout, 'utf-8') ffinfo = json.loads(ff0string) print(json.dumps(ffinfo, indent=4)) # pretty print # print("Video Dimensions: {}x{}".format(ffinfo["streams"][0]["width"], ffinfo["streams"][0]["height"])) # print("Streams Duration:", ffinfo["streams"][0]["duration"]) # print("Format Duration: ", ffinfo["format"]["duration"]) if ("ensemble" in ffinfo["format"]["tags"]): print("ADS ensemble: ", ffinfo["format"]["tags"]["ensemble"]) if ("boundary_condition" in ffinfo["format"]["tags"]): print("ADS boundary_condition: ", ffinfo["format"]["tags"]["boundary_condition"]) if ("init" in ffinfo["format"]["tags"]): print("ADS init: ", ffinfo["format"]["tags"]["init"]) if ("plot" in ffinfo["format"]["tags"]): print("ADS plot: ", ffinfo["format"]["tags"]["plot"]) if ("plot_group" in ffinfo["format"]["tags"]): print("ADS plot_group: ", ffinfo["format"]["tags"]["plot_group"])
def CameraResolution(stream_url): try: GETIMAGE = ffmpy.FFprobe(inputs={ stream_url: None }, global_options=[ '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams' ]).run(stdout=subprocess.PIPE) # extract = re.sub(r'([\\r\\n])',"",str(GETIMAGE)) meta = json.loads(GETIMAGE[0].decode('utf-8')) resExtract = str() for xxx in meta["streams"]: resolutionWidth = xxx["width"] resolutionHeight = xxx["height"] resExtract = str(resolutionWidth) + "," + str(resolutionHeight) except Exception: resExtract = str("0,0") return resExtract
def process_file(path, file): extension = os.path.splitext(file)[1].replace(".", "").lower() filename = os.path.splitext(file)[0] if extension in accept_ext and extension != "": print(file + " is an acceptable extension. Checking file...") else: print(file + " is not an acceptable extension. Skipping...") return print('Processing Started: {:%Y-%m-%d %H:%M:%S}'.format( datetime.datetime.now())) try: tup_resp = ffmpy.FFprobe(inputs={ os.path.join(path, file): None }, global_options=[ '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams' ]).run(stdout=subprocess.PIPE) metaData = json.loads(tup_resp[0].decode('utf-8')) except Exception as file_info_ex: print("File " + file + " is unable to be converted. Adding .PROBE_FAIL to file") move_without_copying_stat( os.path.join(path, filename + "." + extension), os.path.join(path, filename + "." + extension + ".PROBE_FAIL")) return vcodec = '' acodec = '' encode_crf = [] for vs in metaData["streams"]: if "codec_type" in vs and vs["codec_type"] == "video": if vs["codec_name"] == video_type: vcodec = 'copy' print("Video in stream " + str(vs["index"]) + " is " + video_type + ", no conversion needed...") elif vs["codec_name"] != 'mjpeg': vcodec = video_codec if crf: encode_crf = ["-crf", "" + crf] print("Video in stream " + str(vs["index"]) + " is currently " + color.BOLD + color.YELLOW + vs["codec_name"] + color.END + ". Converting to " + color.BOLD + color.YELLOW + video_type + color.END + "...") encode_dif = [] for vs in metaData["streams"]: if "codec_type" in vs and vs[ "codec_type"] == "video" and vcodec != 'copy': if "field_order" in vs and vs["field_order"].find( "progressive") == -1: if deinterlace_ffmpeg: encode_dif = ["-vf", "" + deinterlace_ffmpeg] print("Video in stream " + str(vs["index"]) + " is interlaced, deinterlacing...") else: print("Video in stream " + str(vs["index"]) + " is not interlaced, no deinterlacing needed...") encode_vbr = [] for vs in metaData["streams"]: if "codec_type" in vs and vs["codec_type"] == "audio": if vs["codec_name"] == audio_type: acodec = 'copy' print("Audio in stream " + str(vs["index"]) + " is " + audio_type + ", no conversion needed...") else: acodec = audio_codec if vbr: encode_vbr = ["-vbr", "" + vbr] print("Audio in stream " + str(vs["index"]) + " is currently " + color.BOLD + color.GREEN + vs["codec_name"] + color.END + ". Converting to " + color.BOLD + color.GREEN + audio_type + color.END + "...") if extension == outmode and vcodec == 'copy' and acodec == 'copy' and args.force == False: print(file + " is already encoded properly. (" + outmode + " file and " + video_type + " / " + audio_type + ")\nNo conversion needed. Skipping...\n\n") if strip_title: print("Removing title metadata...") striptitle_out = subprocess.check_output([ atomicparsely_exe, os.path.join(path, file), '--title', '', '--comment', '', '--overWrite' ], stderr=subprocess.STDOUT) print(striptitle_out) return print("Using video codec: " + vcodec + " audio codec: " + acodec + " and Container format " + outformat + " for " + file) print("Duration of current video: " + "{:0>8}".format( datetime.timedelta(seconds=float(metaData["format"]["duration"])))) filename = filename.replace("XVID", video_type) filename = filename.replace("xvid", video_type) enc_resp = "" try: ffargs = ['-y', '-f', outformat, '-acodec', acodec] if encode_dif: ffargs.extend(encode_dif) ffargs.extend(['-vcodec', vcodec]) if encode_crf: ffargs.extend(encode_crf) if additional_ffmpeg: ffargs.extend(additional_ffmpeg.split(" ")) if threads: ffargs.extend(['-threads', str(threads)]) if temp_path: enc_resp = ffmpy.FFmpeg( global_options='-v quiet -stats', inputs={ os.path.join(path, file): None }, outputs={ os.path.join(temp_path, filename + '.temp'): ffargs }).run(stdout=subprocess.PIPE) move_without_copying_stat( os.path.join(temp_path, filename + '.temp'), os.path.join(path, filename + '.' + outmode)) else: enc_resp = ffmpy.FFmpeg(global_options='-v quiet -stats', inputs={ os.path.join(path, file): None }, outputs={ os.path.join(path, filename + '.temp'): ffargs }).run(stdout=subprocess.PIPE) move_without_copying_stat( os.path.join(path, filename + '.temp'), os.path.join(path, filename + '.' + outmode)) if strip_title: print("Removing title metadata...") striptitle_out = subprocess.check_output([ atomicparsely_exe, os.path.join(path, filename + '.' + outmode), '--title', '', '--comment', '', '--overWrite' ], stderr=subprocess.STDOUT) print(striptitle_out) except Exception as e: print("Error: %s" % e) print("Removing temp file and skipping file") if temp_path: if os.path.isfile(os.path.join(temp_path, filename + '.temp')): os.remove(os.path.join(temp_path, filename + '.temp')) else: if os.path.isfile(os.path.join(path, filename + '.temp')): os.remove(os.path.join(path, filename + '.temp')) return if extract_subtitle: sub_resp = "" print("\nExtracting Subtitles...\n") for m in metaData["streams"]: if 'subtitle' in m["codec_type"]: if 'tags' in m: if 'language' in m["tags"]: if m["tags"]["language"] in subtitle_languages.split( " "): try: if 'subrip' in m["codec_name"]: sub_format = 'copy' sub_ext = '.srt' elif mkvextract_exe and 'hdmv_pgs' in m[ "codec_name"]: mkvextract_out = subprocess.check_output( [ mkvextract_exe, 'tracks', os.path.join(path, file), str(m["index"]) + ':' + os.path.join( path, filename + '.' + str(m["index"]) + '.' + m["tags"]["language"] + '.sup') ], stderr=subprocess.STDOUT) continue else: sub_format = 'srt' sub_ext = '.srt' enc_resp = ffmpy.FFmpeg( global_options='-v quiet -stats', inputs={ os.path.join(path, file): None }, outputs={ os.path.join( path, filename + '.' + str(m["index"]) + '.' + m["tags"]["language"] + sub_ext): [ '-y', '-map', '0:' + str(m["index"]), '-c:s:0', sub_format ] }).run(stdout=subprocess.PIPE) print("") except Exception as e: print("Error: %s" % e) print("Deleting subtitle.") if os.path.isfile( os.path.join( path, filename + '.' + str(m["index"]) + '.' + m["tags"]["language"] + sub_ext)): os.remove( os.path.join( path, filename + '.' + str(m["index"]) + '.' + m["tags"]["language"] + sub_ext)) if remover and filename + '.' + outmode != file: print("Deleting original file: " + file) os.remove(os.path.join(path, file)) print('Processing Started: {:%Y-%m-%d %H:%M:%S}'.format( datetime.datetime.now()))
args = parser.parse_args() if args.mode == 'speed': crf = "22" additional_ffmpeg = '-preset superfast -movflags +faststart' if outmode == 'mp4': outformat = 'mp4' elif outmode == 'mkv': outformat = 'matroska' print("Validating FFMpeg configuration...\n") format_resp = ffmpy.FFprobe(inputs={ '': None }, global_options=['-v', 'quiet', '-formats', '2']).run(stdout=subprocess.PIPE, stderr=subprocess.PIPE) if ('E mp4' in format_resp[0]) and ('E matroska' in format_resp[0]): print("You have the suitable formats") else: print("You do not have both the mkv and mp4 formats...Exiting!") exit(1) codec_resp = ffmpy.FFprobe(inputs={ '': None }, global_options=['-v', 'quiet', '-codecs', '2']).run(stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def video_info(in_file, raw=False): info = {} ffprobe = ffmpy.FFprobe(global_options=( "-loglevel quiet -sexagesimal -of json -show_format -show_streams", f'"{in_file}"')) stdout, stderr = ffprobe.run(stderr=subprocess.PIPE, stdout=subprocess.PIPE) ff0string = str(stdout, 'utf-8') ffinfo = json.loads(ff0string) if raw: print(json.dumps(ffinfo, sort_keys=True, indent=4)) info['format'] = mapvinfo(ffinfo, ["format", "format_name"]) info['streams'] = mapvinfo(ffinfo, ["format", "nb_streams"]) info['format_long'] = mapvinfo(ffinfo, ["format", "format_long_name"]) duration = mapvinfo(ffinfo, ["format", "duration"]).split('.') info['duration'] = duration[0] info['bit_rate'] = mapvinfo(ffinfo, ["format", "bit_rate"]) for stream in range(ffinfo["format"]["nb_streams"]): info['stream' + str(stream)] = { 'codec_type': mapvinfo(ffinfo, ["streams", stream, "codec_type"]) } if mapvinfo(ffinfo, ["streams", stream, "codec_type"]) != 'data': info['stream' + str(stream)].update({ 'codec_name': mapvinfo(ffinfo, ["streams", stream, "codec_name"]) }) info['stream' + str(stream)].update({ 'codec_name_long': mapvinfo(ffinfo, ["streams", stream, "codec_long_name"]) }) if mapvinfo(ffinfo, ["streams", stream, "codec_type"]) == 'video': info['stream' + str(stream)].update( {'width': mapvinfo(ffinfo, ["streams", stream, "width"])}) info['stream' + str(stream)].update( {'height': mapvinfo(ffinfo, ["streams", stream, "height"])}) info['stream' + str(stream)].update({ 'aspect_ratio': mapvinfo(ffinfo, ["streams", stream, "display_aspect_ratio"]) }) info['stream' + str(stream)].update({ 'bit_rate': mapvinfo(ffinfo, ["streams", stream, "bit_rate"]) }) #info['stream'+str(stream)].update({'bit_rate': ffinfo["streams"][stream]['tags']["BPS"]}) info['stream' + str(stream)].update( {'level': mapvinfo(ffinfo, ["streams", stream, "level"])}) elif mapvinfo(ffinfo, ["streams", stream, "codec_type"]) == 'audio': info['stream' + str(stream)].update({ 'channels': mapvinfo(ffinfo, ["streams", stream, "channels"]) }) info['stream' + str(stream)].update({ 'bit_rate': mapvinfo(ffinfo, ["streams", stream, "bit_rate"]) }) info['stream' + str(stream)].update({ 'channel_layout': mapvinfo(ffinfo, ["streams", stream, "channel_layout"]) }) info['stream' + str(stream)].update({ 'language': mapvinfo(ffinfo, ["streams", stream, "tags", "language"]) }) info['stream' + str(stream)].update({ 'sample_rate': mapvinfo(ffinfo, ["streams", stream, "sample_rate"]) }) elif mapvinfo(ffinfo, ["streams", stream, "codec_type"]) == 'subtitle': info['stream' + str(stream)].update({ 'language': mapvinfo(ffinfo, ["streams", stream, "tags", "language"]) }) info['stream' + str(stream)].update({ 'title': mapvinfo(ffinfo, ["streams", stream, "tags", "title"]) }) return info
import ffmpy import subprocess import json import math probe = ffmpy.FFprobe( global_options={"-loglevel quiet"}, inputs={ "/home/gobolin/Videos/EncoderTesting/TestFileArchival.mp4": "-print_format json -show_streams" }).run(stdout=subprocess.PIPE) probe_obj = json.loads(probe[0].decode('utf-8')) rate = str(math.floor((float(probe_obj['streams'][0]['duration']) / 10))) print(rate) thumb = ffmpy.FFmpeg( global_options={"-v quiet"}, inputs={"/home/gobolin/Videos/EncoderTesting/TestFileArchival.mp4": None}, outputs={ "images/thumbnail.%d.png": ['-vf', 'fps=1/' + rate], "images/thumbnail.%d.tn.png": ['-vf', 'fps=1/' + rate, '-s', '160x90'] }) thumb.run()
def get_title_tag(media_file): """ Retrieve the title tag from the metadata of the specified media_file using the ffprobe command and return it as a unicode string. """ media_file = ensure_unicode(media_file) ext = os.path.splitext(media_file)[1].lower() # When invoking a system command, its command line arguments need to be # byte strings in file system encoding. If we pass command line # arguments as unicode strings, the subcommand package implementation # encodes them to byte strings using the 'ascii' encoder, which fails # if they contain non-ASCII characters. media_file_b = media_file.encode(sys.getfilesystemencoding()) # The title tag (INAM) in AVI files very often does not use UTF-8 encoding, # but cp1252 or the like. The ffprobe command assumes the title tag is # encoded in UTF-8. When non-ASCII characters are in the title tag, the # ffprobe command by default issues a warning and replaces the character # with the Unicode replacement character (U+FFFD). The 'sv=ignore' writer # option causes ffprobe to ignore non-ASCII characters and to return them # unchanged. ffprobe = ffmpy.FFprobe(global_options=[ '-hide_banner', '-show_format', '-of', 'json=sv=ignore' ], inputs={media_file: None}) try: stdout, stderr = ffprobe.run(stdout=subprocess.PIPE, stderr=subprocess.PIPE) except (UnicodeDecodeError, UnicodeEncodeError) as exc: print("Error: Unicode conversion issue when invoking {cmd!r}: " "{msg!r}".format(cmd=ffprobe.cmd, msg=exc)) return 1 except ffmpy.FFRuntimeError as exc: print("Error: ffprobe failed on media file {file!r}: {msg!r}".format( file=media_file, msg=exc)) return 1 if ext == '.avi': stdout_u = None for enc in AVI_METADATA_ENCODINGS: try: stdout_u = ensure_unicode(stdout, encoding=enc) except UnicodeDecodeError as exc: continue if stdout_u is None: print("Error: Cannot decode ffprobe metadata output for AVI file " "{file!r} using any of the encodings {enc}: {out!r}".format( file=media_file, out=stdout, encs=','.joinAVI_METADATA_ENCODINGS())) return 1 else: stdout_u = ensure_unicode(stdout) # UTF-8 by default try: out = json.loads(stdout_u) except ValueError: print("Error: ffprobe returned invalid JSON for media file " "{file!r}: {out!r}".format(file=media_file, out=stdout_u)) return 1 tags = out['format'].get('tags', dict()) title_tag = tags.get('title', None) return title_tag
import ffmpy import subprocess import json import cv2 from Image2DCT.Image2DCT import Image2DCT video = "1_1_Y.flv" fp = ffmpy.FFprobe(inputs={video: ['-show_entries', 'frame=pict_type,coded_picture_number', '-of', 'json']}) stdout, stderror = fp.run(stdout=subprocess.PIPE) d = json.loads(stdout) frameList = list() for i in d['frames']: if len(i) != 0 and i['pict_type'] == "I": frameList.append(i['coded_picture_number']) continue cap = cv2.VideoCapture(video) for frameNumber in frameList: if cap.isOpened(): cap.set(cv2.CAP_PROP_POS_FRAMES, frameNumber+1) ret, frame = cap.read() length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
fullname = filename.strip('.mp4') year = fullname[-4:] month = fullname[-8:-6] day = fullname[-6:-4] name = fullname[:-11] logging.basicConfig(filename= 'cctv-encoder.log', filemode='a', level=logging.DEBUG, format='%(asctime)s:%(levelname)s: ' + fullname +': %(message)s') outpath = outpathbase + '/' + fullname + '/' os.makedirs(outpath,exist_ok=True) #PROBE probe = ffmpy.FFprobe( global_options={"-loglevel quiet"}, inputs={ inpath+filename : "-print_format json -show_streams"} ).run(stdout= subprocess.PIPE) probe_obj = json.loads(probe[0].decode('utf-8')) logging.info(probe_obj) #VIDEO ff = ffmpy.FFmpeg( global_options={'-y -v quiet -stats'}, inputs={ inpath+filename : None }, outputs={ outpath + fullname + '.broadband.mp4': '-vf "scale=-2:720" -b:v 1M'} )
def update_movies(file_path=None,filename=None): print ('db_utils: update_movies') files_list = rescan_base_dir(file_path,filename) # check video files for metadata using ffprobe for item in files_list: print('file:',item) # TODO: use ffmpeg to extract metadata from each file for database ffprobe = ffmpy.FFprobe(global_options="-show_format -of json", inputs={item['path'] : None}) print("ffprobe.cmd:", ffprobe.cmd) # printout the resulting ffprobe shell command stdout, stderr = ffprobe.run(stderr=subprocess.PIPE, stdout=subprocess.PIPE) # std* is byte sequence, but json in Python 3.5.2 requires str ff0string = str(stdout,'utf-8') ffinfo = json.loads(ff0string) # print(json.dumps(ffinfo, indent=4)) # pretty print metadataEnsemble = None metadataBC = None metadataInit = None metadataPlot = None metadataPlotGroup = None initDTObj = None if ("ensemble" in ffinfo["format"]["tags"]): # print("ADS ensemble: ", ffinfo["format"]["tags"]["ensemble"]) metadataEnsemble = ffinfo["format"]["tags"]["ensemble"] if ("boundary_condition" in ffinfo["format"]["tags"]): # print("ADS boundary_condition: ", ffinfo["format"]["tags"]["boundary_condition"]) metadataBC = ffinfo["format"]["tags"]["boundary_condition"] if ("init" in ffinfo["format"]["tags"]): # print("ADS init: ", ffinfo["format"]["tags"]["init"]) metadataInit = ffinfo["format"]["tags"]["init"] # initDTObj = datetime.strptime(metadataInit, "%Y-%m-%dT%H:%M:%S%z") initDTObj = datetime.strptime(metadataInit, "%Y-%m-%dT%H:%M:%S") if ("plot" in ffinfo["format"]["tags"]): # print("ADS plot: ", ffinfo["format"]["tags"]["plot"]) metadataPlot = ffinfo["format"]["tags"]["plot"] if ("plot_group" in ffinfo["format"]["tags"]): # print("ADS plot_group: ", ffinfo["format"]["tags"]["plot_group"]) metadataPlotGroup = ffinfo["format"]["tags"]["plot_group"] print("ADS ensemble: ", metadataEnsemble) print("ADS boundary_condition: ", metadataBC) print("ADS init: ", metadataInit) print("ADS plot: ", metadataPlot) print("ADS plot_group: ", metadataPlotGroup) if ((not (metadataEnsemble is None)) and \ (not (metadataBC is None)) and \ (not (metadataInit is None)) and \ (not (metadataPlot is None)) and \ (not (metadataPlotGroup is None))): print('saving Movie to mongodb') Movie( name = item['name'], path = item['path'], file = item['file'], # file_id is primary key! file_id = item['file'], # fields for AtmosphericDataSolutions weather videos ensemble = metadataEnsemble, boundary_condition = metadataBC, init_date = initDTObj, plot = metadataPlot, plot_group = metadataPlotGroup ).save() else: print('skipping movie') # Movie( # name = item['name'], # path = item['path'], # file = item['file'], # # file_id is primary key! # file_id = item['file'] # ).save() return "success"
def populate(): # Finds all titles from IA API under the Film Noir collection, filtering out known unwanted files for i in search_items('collection:Film_Noir', list_of_meta_keys): if "Weirdness Bad Movie" in i['title'] or i['title'] == 'Sobaka': continue identifier = i['identifier'] title = i['title'] collection = i.get('collection', ['Film_Noir']) description = i.get('description', 'no description') tags = i.get('subject', []) if type(tags) is not list: tags = list(tags) item = get_item(identifier) # Finds first file in list of files with ".mp4" file_name = next(filter(lambda x: ".mp4" in x['name'], item.files), None)['name'] # Determines url based on ID and file name url = f"https://archive.org/download/{identifier}/{file_name}" # Runs FFprobe on file to pull metadata about the file probe = ffmpy.FFprobe(inputs={url: None}, global_options=[ '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams' ]) stdout, _ = probe.run(stdout=subprocess.PIPE) probe_data = json.loads(stdout.decode('utf-8'))['streams'][0] duration = probe_data.get('duration', 0) resolution_width = probe_data.get('width', 640) resolution_height = probe_data.get('height', 480) frame_rate = probe_data.get('avg_frame_rate', "30000/1001") # If frame rate is 0, there will probably be errors in encoding later on, so it will not be stored in database if frame_rate == "0/0": continue # Runs FFmpeg to detect shot breaks in file, which are sent out on the stderr stream ff = ffmpy.FFmpeg( inputs={url: '-hide_banner'}, outputs={ "pipe:1": '-an -filter:v "select=\'gt(scene, 0.3)\', showinfo" -f null' }) ff.cmd _, stderr = ff.run(stdout=subprocess.PIPE, stderr=subprocess.PIPE) shot_log = stderr.decode("utf-8").split("\n") # Filters out data to pull times filtered_output = list( filter(lambda x: "Parsed_showinfo_1" in x and "pts_time" in x, shot_log)) # Further filtering of data to make a list timecodes = list( map( lambda y: ((next( filter(lambda z: z.startswith("pts_time"), y.split(" ")), None)).split(":"))[1], filtered_output)) # Creates film instance in database including all of the above data film = Film.objects.get_or_create(collection=collection, description=description, identifier=identifier, tags=tags, title=title, file_name=file_name, url=url, timecodes=timecodes, duration=duration, resolution_width=resolution_width, resolution_height=resolution_height, frame_rate=frame_rate) print(film)
def showProperty(self): # Show input video property in text browser self.fileProperty.clear() # Refresh fileProperty widget each time openFile() is called meta = ffmpy.FFprobe(executable='ffprobe', inputs={ self.model.getFileName(): ' -v error -print_format json -show_format -show_streams'}).run( stdout=subprocess.PIPE) output = json.loads(meta[0].decode('utf-8')) self.length = float(output['format']['duration']) if self.length > 3603599.999: errorMsg = QtWidgets.QMessageBox() errorMsg.setText('File Error.') errorMsg.setWindowTitle('Error') errorMsg.setDetailedText('Input file size exceeds limit.') errorMsg.exec() return # Set maximum acceptable input file length defaultEndTrimHour, defaultEndTrimMinute, defaultEndTrimSecond = self.convert(second=self.length) self.eH.setValue(int(defaultEndTrimHour)) self.eM.setValue(int(defaultEndTrimMinute)) self.eS.setValue(defaultEndTrimSecond) data = ['Media Name: ' + output['format']['filename'], 'Media Duration: ' + output['format']['duration'] + ' s', 'Media Size: ' + str(eval(output['format']['size'] + '/1048576')) + ' MB'] try: data.append('Media Encoder: ' + output['format']['tags']['encoder']) except: data.append('Media Encoder: undefined') # In some situations ffprobe cannot get Media encoder in 'tags', use 'except' to avoid return error try: data.append('Video Codec Name: ' + output['streams'][0]['codec_name']) except: try: data.append('Video Codec Name: ' + output['streams'][1]['codec_name']) except: data.append('Video Codec Name: undefined') try: data.append('Video Codec Long Name: ' + output['streams'][0]['codec_long_name']) except: try: data.append('Video Codec Long Name: ' + output['streams'][1]['codec_long_name']) except: data.append('Video Codec Long Name: undefined') try: data.append('Resolution: ' + str(output['streams'][0]['width']) + 'x' + str(output['streams'][0]['height'])) except: try: data.append( 'Resolution: ' + str(output['streams'][1]['width']) + 'x' + str(output['streams'][1]['height'])) except: data.append('Resolution: undefined') try: data.append('FPS: ' + str(eval(output['streams'][0]['avg_frame_rate']))) except: try: data.append('FPS: ' + str(eval(output['streams'][1]['avg_frame_rate']))) except: data.append('FPS: undefined') try: data.append('Audio Codec Name: ' + output['streams'][1]['codec_name']) except: try: data.append('Audio Codec Name: ' + output['streams'][0]['codec_name']) except: data.append('Audio Codec Name: undefined') try: data.append('Audio Codec Long Name: ' + output['streams'][1]['codec_long_name']) except: try: data.append('Audio Codec Long Name: ' + output['streams'][0]['codec_long_name']) except: data.append('Audio Codec Long Name: undefined') try: data.append('Bit Rate: ' + str(eval(output['streams'][1]['bit_rate'] + '/1000')) + ' kb') except: try: data.append('Bit Rate: ' + str(eval(output['streams'][0]['bit_rate'] + '/1000')) + ' kb') except: data.append('Bit Rate: undefined') # Extract other important properties for element in data: self.fileProperty.append(element)