Created
November 16, 2019 03:18
-
-
Save dcbark01/1a695c6c301bdb144529e092c533e70a to your computer and use it in GitHub Desktop.
Convenient class for getting video metadata
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
@author: dcbark01 | |
@date: Nov 2019 | |
@license: MIT | |
""" | |
import os | |
import json | |
import shlex | |
import subprocess | |
def split_filepath(path_to_file): | |
base_path, filename_with_ext = os.path.split(path_to_file) | |
base_name, file_ext = filename_with_ext.split(".") | |
return (base_path, base_name, file_ext) | |
def get_video_metadata(filename, print_output=False): | |
vid_fullname = os.path.abspath(filename) | |
cmd_str = f"ffprobe -v error -print_format json -show_format -show_streams '{vid_fullname}'" | |
# print(cmd_str) | |
output = json.loads(subprocess.run(shlex.split(cmd_str), check=True, stdout=subprocess.PIPE).stdout) | |
if print_output: | |
pprint(output) | |
return output | |
class VidMetadata(object): | |
def __init__(self, input_file, stream_num=0): | |
self._md = get_video_metadata(input_file) | |
self._format = self._md["format"] | |
self._streams = self._md["streams"][stream_num] | |
# Read-only video attributes from ffprobe JSON response | |
self._filename = "" | |
self._format_name = "" | |
self._fps = -1 | |
self._duration = -1.0 | |
self._num_frames = -1 | |
self._size = -1 | |
self._resolution = (-1, -1) | |
@property | |
def filename(self): | |
return self._filename | |
@filename.getter | |
def filename(self): | |
return self._format["filename"] | |
@property | |
def format_name(self): | |
return self._format_name | |
@format_name.getter | |
def format_name(self): | |
return self._format["format_name"] | |
@property | |
def fps(self): | |
return self._fps | |
@fps.getter | |
def fps(self): | |
num, den = [int(i) for i in self._streams["avg_frame_rate"].split("/")] | |
fps = int(num / den) | |
return fps | |
@property | |
def duration(self): | |
return self._duration | |
@duration.getter | |
def duration(self): | |
return float(self._streams["duration"]) | |
@property | |
def num_frames(self): | |
return self._num_frames | |
@num_frames.getter | |
def num_frames(self): | |
return int(self._streams["nb_frames"]) | |
@property | |
def size(self): | |
return self._size | |
@size.getter | |
def size(self): | |
return int(self._format["size"]) | |
@property | |
def resolution(self): | |
return self._resolution | |
@resolution.getter | |
def resolution(self): | |
""" Resolution as 2-tuple (height x width)""" | |
height = int(self._streams["height"]) | |
width = int(self._streams["width"]) | |
return (height, width) | |
def print_data(self): | |
print(f"Video Filename = {self.filename}") | |
print(f"Video Format = {self.format_name}") | |
print(f"Video FPS (frames/sec) = {self.fps}") | |
print(f"Video Duration (sec) = {self.duration}") | |
print(f"Video Total Frames = {self.num_frames}") | |
print(f"Video Size (MB) = {self.size}") | |
print(f"Video Resolution (h x w) = {self.resolution}") | |
def _print_raw_ffmpeg_json(self): | |
""" Might occasionally be useful for debugging. """ | |
pprint(self._md) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment