async def _concat(self, ctx, vstream, astream, kwargs): first_vid_filepath = kwargs['first_vid_filepath'] second_vid_filepath = kwargs['input_filename'] target_width = 640 target_height = 480 first_vid_metadata = FFProbe(first_vid_filepath) second_vid_metadata = FFProbe(second_vid_filepath) for stream in first_vid_metadata.streams + second_vid_metadata.streams: if(stream.is_video()): width, height = stream.frame_size() target_width = min(target_width, width) target_height = min(target_height, height) first_stream = ffmpeg.input(first_vid_filepath) vfirst = ( first_stream.video .filter('scale', w=target_width, h=target_height) .filter('setsar', r='1:1') ) afirst = first_stream.audio vstream = ( vstream .filter('scale', w=target_width, h=target_height) .filter('setsar', r='1:1') ) joined = ffmpeg.concat(vfirst, afirst, vstream, astream, v=1, a=1).node return (joined[0], joined[1], {'vsync':0})
def getFileLengthMs(self, fileName, isAudio=False): if not isAudio: ms = int(float(FFProbe(fileName).video[0].duration) * 1000) # duration in milliseconds else: ms = int(float(FFProbe(fileName).audio[0].duration) * 1000) # duration in milliseconds return ms
def test_bitrate(self): try: media = FFProbe(test_videos[0], show_streams=True, show_packets=True) packets_by_stream = media.get_packets_by_stream() for stream_index, packets in packets_by_stream.items(): bytes = sum([packet.size() for packet in packets], 0) print( 'Stream bitrate:', bytes * 8 / (media.streams()[stream_index].duration_seconds() * 1000)) except Exception as e: raise e
def test_sample_media(self): samples = [ f for f in listdir(self.tmp_dir) if isfile(join(self.tmp_dir,f)) ] for sample in samples: print "Probing " + sample metadata = FFProbe(self.tmp_dir + "/" + sample) print "HTML5 Media Source Type: " + metadata.html5SourceType() self.assertNotEqual(metadata.durationSeconds(), 0.0) self.assertNotEqual(metadata.bitrate(), 0.0) for stream in metadata.streams: if stream.isAudio() or stream.isVideo(): self.assertNotEqual(stream.durationSeconds(), 0.0) if stream.isVideo(): self.assertNotEqual(stream.frameSize(), (0,0))
def main(video): if not video.exists(): video = SOURCE / video.name if not DEBUG: folder = DEST / video.stem folder.mkdir(exist_ok=True) name = folder / video.name # read file, get time, framerate and duration try: stream = FFProbe(str(video)).streams[0] start_time = get_time(stream.start_time) framerate = stream.framerate duration = get_time(stream.duration_seconds()) except: stream = VideoFileClip(str(video)) start_time = get_time(stream.start) framerate = stream.fps duration = get_time(stream.duration) # get scene timestamps scenes = find_scenes(video, framerate) if get_time(scenes[0][0]) != start_time: scenes.insert(0, (start_time, scenes[0][0])) [print(scene) for scene in scenes] # get individual clips for num, (start, end) in enumerate(scenes, start=1): if num == 1: start, end = start_time, get_time(end) elif num == len(scenes) + 1: start, end = get_time(start), duration else: start, end = get_time(start), get_time(end) if start > end: start, end = end, start if start == end: continue if DEBUG: print(start, end) continue file = name.with_name(f'{name.stem} - {num:03}.mp4') trim(str(video), str(file), start, end)
def test_video(video, complexity): metadata=FFProbe(video) coding_res = int(metadata.video[0].height)*int(metadata.video[0].width) bitrate = int(re.search(r'\d+', metadata.metadata['bitrate']).group()); framerate = int(metadata.video[0].framerate); test_model(bitrate, coding_res, framerate, complexity)
def test_sample_media(self): samples = [ f for f in listdir(self.tmp_dir) if isfile(join(self.tmp_dir, f)) ] for sample in samples: print("Probing " + sample) metadata = FFProbe(self.tmp_dir + "/" + sample) print("HTML5 Media Source Type: " + metadata.html5SourceType()) self.assertNotEqual(metadata.durationSeconds(), 0.0) self.assertNotEqual(metadata.bitrate(), 0.0) for stream in metadata.streams: if stream.isAudio() or stream.isVideo(): self.assertNotEqual(stream.durationSeconds(), 0.0) if stream.isVideo(): self.assertNotEqual(stream.frameSize(), (0, 0))
def get_tags(driver, path, filter=False): tags = set() frames = [] video = path.suffix in ('.gif', '.webm', '.mp4') if video: tags.add('animated') if path.suffix in ('.webm', '.mp4'): try: for stream in FFProbe(str(path)).streams: if stream.codec_type == 'audio': tags.add('audio') break except: pass temp_dir = tempfile.TemporaryDirectory() vidcap = VideoCapture(str(path)) success, frame = vidcap.read() while success: temp = ROOT.parent / temp_dir.name / f'{next(tempfile._get_candidate_names())}.jpg' temp.write_bytes(imencode('.jpg', frame)[-1]) frames.append(temp) success, frame = vidcap.read() else: step = 90 * log((len(frames) * .002) + 1) + 1 frames = frames[::round(step)] else: frames.append(path) for frame in frames: driver.get('http://dev.kanotype.net:8003/deepdanbooru/') driver.find('//*[@id="exampleFormControlFile1"]', str(frame)) driver.find('//button[@type="submit"]', click=True) for _ in range(4): html = bs4.BeautifulSoup(driver.page_source(), 'lxml') try: tags.update([ tag.text for tag in html.find('tbody').findAll(href=True) ]) break except AttributeError: if driver.current_url().endswith('deepdanbooru/'): driver.find('//*[@id="exampleFormControlFile1"]', str(frame)) driver.find('//button[@type="submit"]', click=True) driver.refresh() else: if video: temp_dir.cleanup() if filter: tags.difference_update(REMOVE) return ' '.join(tags)
def test_ff(): if len(sys.argv[1:]) != 1: logging.error("Wrong number of input arguments!") sys.exit() inputfile = sys.argv[1] m = FFProbe(inputfile) v_num = len(m.video) a_num = len(m.audio) #assert v_num==1 and a_num==1 vst = m.video ast = m.audio #vcodec=vst.codec() #acodec=ast.codec() fmt = m.format print 'format:' print '\tformat_name=%s' % fmt.formatName() for a in vst: print 'video:' print '\tcodec_name=%s description=%s' % (a.codecName(), a.codecDescription()) for a in ast: print 'audio:' print '\tcodec_name=%s description=%s language=%s' % ( a.codecName(), a.codecDescription(), a.language())
def fetchStimuli(count = None, modality = None, forceImport = False): if forceImport: from os import path, listdir from ffprobe import FFProbe # TODO: Expand to support audio-only modality. stimLocation = path.relpath(path.dirname(__file__)) + "/" + app.config["stim_base"] stimFiles = listdir(stimLocation) stimObjs = [] for stimFile in stimFiles: # Only look at .mp4 files # Check if a stimulus with this filename already exists, and add it if not. if stimFile.endswith(".mp4") and models.Stimulus.query.filter_by(filename = stimFile).first() is None: durationStr = FFProbe(stimLocation + stimFile).video[0].duration duration = int(round(float(durationStr))) stimObj = models.Stimulus(filename = stimFile, modality = "video", duration = duration) stimObjs.append(stimObj) try: db.session.add_all(stimObjs) db.session.commit() except Exception as error: print("Error adding stimuli to database", error) query = models.Stimulus.query.order_by(models.Stimulus.id) if modality: query = query.filter_by(modality = modality) if app.config.get("tags"): query = query.filter_by(tags = app.config["tags"]) if count: query = query.limit(count) results = query.all() return results
def is_video(self): if os.path.exists(self.video_path): metadata = FFProbe(self.video_path) if len(metadata.streams) > 0: if metadata.streams[0].is_video(): return True return False
def get_video_duration(video_file): """Get video duration in seconds""" try: return float(FFProbe(video_file).video[0].duration) except Exception as e: print("could not extract duration from video {} due to {}".format( video_file, e)) return None
def get_tags(driver, path, filter=False): tags = set() frames = [] video = path.suffix in ('.gif', '.webm', '.mp4') if video: tags.add('animated') if path.suffix in ('.webm', '.mp4'): try: for stream in FFProbe(str(path)).streams: if stream.codec_type == 'audio': tags.add('audio') break except: pass vidcap = VideoCapture(str(path)) frame_count = int(vidcap.get(CAP_PROP_FRAME_COUNT)) vidcap.release() elif path.suffix in ('.gif'): gifcap = GifImagePlugin.GifImageFile(str(path)) frame_count = gifcap.n_frames gifcap.close() step = 90 * log((frame_count * .002) + 1) + 1 frames = video_generator(path, round(step)) else: frames.append(path) for frame in frames: driver.get('http://dev.kanotype.net:8003/deepdanbooru/') driver.find('//*[@id="exampleFormControlFile1"]', str(frame)) driver.find('//button[@type="submit"]', click=True) for _ in range(4): html = bs4.BeautifulSoup(driver.page_source(), 'lxml') try: tags.update([ tag.text for tag in html.find('tbody').findAll(href=True) ]) break except AttributeError: if driver.current_url().endswith('deepdanbooru/'): driver.find('//*[@id="exampleFormControlFile1"]', str(frame)) driver.find('//button[@type="submit"]', click=True) driver.refresh() if filter: tags.difference_update(REMOVE) return ' '.join(tags)
def get_stream(files, text): new = DEST / files[0].with_suffix('.mp4').name if text and text in ('y', 'ye', 'yes'): stream = [ ffmpeg.input(str(file)).drawtext( text=file.stem, fontsize=45, x=int(FFProbe(file).streams[0].width) * .70, y=int(FFProbe(file).streams[0].height) * .85, shadowcolor='white', shadowx=2, shadowy=2 ) for file in files ] else: stream = [ffmpeg.input(str(file)) for file in files] return new, stream
def detect_file(input_file): m = FFProbe(input_file) vst = m.video assert len(vst) == 1 ast = m.audio sst = m.subtitle fmt = m.format return fmt, vst, ast, sst
def get_codec(path: str): try: metadata = FFProbe(path) except: return None if 'video' in metadata.streams: return metadata.video[0].codec_name return metadata.audio[0].codec_name
def stab_file(self, input_path, output_path): zoomed_file_name = "zoomed.mp4" metadata = FFProbe(input_path) if len(metadata.video) > 1: raise VideoBrokenException( "Video may not contain multiple video streams") if len(metadata.video) < 1: raise VideoBrokenException("No video streams found in file") could_check_dur_initially = self.check_vid_duration(input_path) try: # zoom by the size of the zoom in the stabilization, the total output file is bigger, # but no resolution is lost to the crop subprocess.check_output( [ self.ffmpeg_full_path, "-y", "-i", input_path, "-vf", "scale=trunc((iw*" + self.video_scale_factor + ")/2)*2:trunc(ow/a/2)*2", "-pix_fmt", "yuv420p", # workaround for https://github.com/georgmartius/vid.stab/issues/36 zoomed_file_name ], stderr=subprocess.STDOUT) if not could_check_dur_initially: # sometimes metadata on original vids were broken, # so we need to re-check after fixing it during the first ffmpeg-pass self.check_vid_duration(zoomed_file_name) subprocess.check_output([ self.ffmpeg_full_path, "-y", "-i", zoomed_file_name, "-vf", "vidstabdetect", "-f", "null", "-" ], stderr=subprocess.STDOUT) subprocess.check_output([ self.ffmpeg_full_path, "-y", "-i", zoomed_file_name, "-vf", "vidstabtransform=smoothing=20:crop=black:zoom=" + self.video_zoom_factor + ":optzoom=0:interpol=linear,unsharp=5:5:0.8:3:3:0.4", output_path ], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as cpe: print "cpe.returncode", cpe.returncode print "cpe.cmd", cpe.cmd print "cpe.output", cpe.output raise VideoStabilisingException, "ffmpeg could't compute file", cpe
def test_video(self): for test_video in test_videos: try: media = FFProbe(test_video) self.assertIsNotNone(media) print('File:', test_video) print_ffprobe(media) except FFProbeError as e: raise e except Exception as e: raise e
def test_stream(self): for test_stream in test_streams: try: media = FFProbe(test_stream) self.assertIsNotNone(media) print('Stream URL:', test_stream) print_ffprobe(media) except FFProbeError as e: raise e except Exception as e: raise e
def getmediainfo(location): metadata = FFProbe(location) isvideo = False if len(metadata.streams) < 1: return None for stream in metadata.streams: if stream.is_video(): isvideo = True if isvideo: return "video" else: return "audio"
def walk_tree(path): for root, dirs, files in os.walk(path): for file in files: if check_extension(file): pathname = os.path.join(root, file) metadata = FFProbe(pathname) try: length = metadata.streams[0].durationSeconds() except (IndexError): print os.path.join(root, file) + " was a problem file. skipped." continue output_table.append((pathname, length))
def get_video_start_time(video_file): """Get video start time in seconds""" try: time_string = FFProbe(video_file).video[0].creation_time try: creation_time = datetime.datetime.strptime(time_string, TIME_FORMAT) except: creation_time = datetime.datetime.strptime(time_string, TIME_FORMAT_2) except: return None return creation_time
def check_vid_duration(self, path): metadata = FFProbe(path) if hasattr(metadata.video[0], "duration") \ and is_number(metadata.video[0].duration): if float(metadata.video[0].duration ) > self.max_video_length_seconds: raise VideoBrokenException("Video too long. Video duration: " + metadata.video[0].duration + ", Maximum duration: " + str(self.max_video_length_seconds) + ". ") else: return True return False
def transcribe_file(speech_file): client = speech.SpeechClient() with io.open(speech_file, 'rb') as audio_file: content = audio_file.read() metadata = FFProbe(speech_file) sample_rate = int(metadata.audio[0].sample_rate) audio = types.RecognitionAudio(content=content) config = types.RecognitionConfig( encoding=enums.RecognitionConfig.AudioEncoding.OGG_OPUS, language_code='ru-RU', sample_rate_hertz=sample_rate) response = client.recognize(config, audio) for result in response.results: return result.alternatives[-1].transcript
def get_video_start_time(video_file): """Get video start time in seconds""" if not os.path.isfile(video_file): print("Error, video file {} does not exist".format(video_file)) return None try: time_string = FFProbe(video_file).video[0].creation_time try: creation_time = datetime.datetime.strptime(time_string, TIME_FORMAT) except: creation_time = datetime.datetime.strptime(time_string, TIME_FORMAT_2) except: return None return creation_time
def get_media_params(file_path): m = Metadata() try: metadata = FFProbe(file_path) if metadata.html5SourceType() != "": m.add("html5_source_type", metadata.html5SourceType()) if metadata.bitrate() != 0.0: m.add("bit_rate", metadata.bitrate()) if metadata.durationSeconds() != 0.0: m.add("duration", metadata.durationSeconds()) for stream in metadata.streams: if stream.isVideo(): (width, height) = stream.frameSize() if int(width) != 0 and int(height) != 0: m.add("width", width) m.add("height", height) if int(stream.frames()) != 0: m.add("frames", stream.frames()) except Exception as e: pass """Fallback and calculate bit rate or duration if missing using available data""" if m.exists("bit_rate") and m.exists("duration") is False: size = os.path.getsize(full_path) m.add("duration", (m.get("bit_rate") / 8) * size) if m.exists("duration") and m.exists("bit_rate") is False: size = os.path.getsize(full_path) m.add("bit_rate", (size / m.get("duration")) * 8) if m.exists("frames") and m.exists( "duration") and m.exists("frame_rate") is False: m.add("frame_rate", int(m.get("frames") / m.get("duration"))) """If we have some values then return them if not then return False""" if m.empty() is False: return m return False
def ffmpeg(file_input, root_output='output'): """ Transcode files :param file_input: Name of the file to transcode. :return: """ # output_dir = os.path.join(source_dir, '/', os.path.dirname(file_input)) output_dir = os.path.join( root_output, os.path.normpath( os.path.relpath(os.path.dirname(file_input), source_dir))) click.echo("Folders: " + output_dir) if os.path.exists(output_dir): click.echo("Folder " + output_dir + " already exists.") else: os.makedirs(output_dir) duration = 0 start_time = current_milli_time() metadata = FFProbe(file_input) for stream in metadata.streams: click.echo( str(stream.durationSeconds()) + " seconds for " + os.path.basename(file_input)) duration = stream.durationSeconds() try: ff = ffmpy.FF(inputs={file_input: None}, outputs={ os.path.abspath( os.path.join(output_dir, os.path.basename(file_input))): FFMPEG_OPTIONS }) click.echo(ff.cmd_str) ff.run() except: return "Problem with " + file_input end_time = current_milli_time() return "Converted " + str(duration) + " in ~" + str( round((end_time - start_time) / 1000 / 60))
def generateScreenshot(file_): m = FFProbe(file_) for s in m.streams: if s.isVideo(): framerate = s.frames() / s.durationSeconds() print "framerate " + str(framerate) print "frameSize " + str(s.frameSize()) print "durationSeconds " + str(s.durationSeconds()) print "frames " + str(s.frames()) print "isVideo " + str(s.isVideo()) print "sec2time " + str(sec2time(s.durationSeconds())) minutes = getMinutes(s.durationSeconds()) print "minutes " + str(minutes) #return for i in range(5, int(minutes), 5): print "minutes = " + str(i) hms = min2time(i) print "hms = " + hms longtime = hms.replace(':', '') print "longtime = " + longtime timeasstring = hms image = file_ + '_' + longtime + '.jpg' print "target img= " + image inFile = file_ outFile = image if os.path.isfile(outFile): print "skipping existing file " + outFile continue ff = FFmpeg(inputs={inFile: '-y -ss ' + timeasstring}, outputs={outFile: '-vframes 1 -q:v 2'}) # ffmpeg -y -ss 00:${i}:00 -i \""$file"\" -vframes 1 -q:v 2 \""${file}_00${i}00"\".jpg # -y = overwrite output file # -ss = seek to this time so not every frame is parsed print ff.cmd ff.run()
def _get_stats(self): # TODO refactor to consume path on event, potentially from queue stats = list() for path in self.watch_path.glob("*.mkv"): metadata = FFProbe(path.name) video_stream_id = 0 audio_tracks = list() has_dts = False dts_tracks = 0 sub_tracks = 0 has_lang = False for idx, stream in enumerate(metadata.streams): if stream.is_video(): video_stream_id = idx if stream.is_audio(): audio_tracks.append({ "codec": stream.codec(), "stream_id": idx, "stream_name": stream.__dict__.get("TAG:title", None), }) if stream.codec() == "dts": dts_tracks += 1 has_dts = True if stream.is_subtitle(): sub_tracks += 1 if stream.language() == "rum": has_lang = True fstat = { "file_path": path, "video_stream_id": video_stream_id, "audio_tracks": audio_tracks, "has_dts": has_dts, "dts_tracks": dts_tracks, "sub_tracks": sub_tracks, "has_lang": has_lang, } stats.append(fstat) return stats
def test_stream(): for test_stream in test_streams: media = FFProbe(test_stream) print('File:', test_stream) print('\tStreams:', len(media.streams)) for index, stream in enumerate(media.streams, 1): print('\tStream: ', index) try: if stream.is_video(): frame_rate = stream.frames() / stream.duration_seconds() print('\t\tFrame Rate:', frame_rate) print('\t\tFrame Size:', stream.frame_size()) print('\t\tDuration:', stream.duration_seconds()) print('\t\tFrames:', stream.frames()) print('\t\tIs video:', stream.is_video()) except FFProbeError as e: print(e) except Exception as e: print(e)
def get_video_startime(self, video_file): """Estimate start date of video file using its metadata. Note that this method might give incorrect results depending on the recording device. Only tested for videos recorded on Android.""" metadata = FFProbe(video_file) start_time_str = metadata.metadata['creation_time'] duration_str = metadata.metadata['Duration'] if 'Z' not in start_time_str: print("Warning: Video timestamp not in UTC") start_time = dateutil.parser.isoparse( start_time_str) # Start time of video in UTC duration_t = dateutil.parser.parse( duration_str) # Start time of video in UTC duration = datetime.timedelta(hours=duration_t.hour, minutes=duration_t.minute, seconds=duration_t.second) start_time_in_secs = start_time.timestamp() - duration.total_seconds() return start_time_in_secs
def get_media_params(file_path): m = Metadata() try: metadata = FFProbe(file_path) if metadata.html5SourceType() != "": m.add("html5_source_type", metadata.html5SourceType()) if metadata.bitrate() != 0.0: m.add("bit_rate", metadata.bitrate()) if metadata.durationSeconds() != 0.0: m.add("duration", metadata.durationSeconds()) for stream in metadata.streams: if stream.isVideo(): (width,height) = stream.frameSize() if int(width) != 0 and int(height) != 0: m.add("width",width) m.add("height",height) if int(stream.frames()) != 0: m.add("frames",stream.frames()) except Exception as e: pass """Fallback and calculate bit rate or duration if missing using available data""" if m.exists("bit_rate") and m.exists("duration") is False: size = os.path.getsize(full_path) m.add("duration", (m.get("bit_rate")/8) * size) if m.exists("duration") and m.exists("bit_rate") is False: size = os.path.getsize(full_path) m.add("bit_rate", (size / m.get("duration"))*8) if m.exists("frames") and m.exists("duration") and m.exists("frame_rate") is False: m.add("frame_rate", int(m.get("frames")/m.get("duration"))) """If we have some values then return them if not then return False""" if m.empty() is False: return m return False