Added black frame detection, srt parser and exif tags population

pull/1567/head
Luca Di Leo 2023-01-09 11:45:22 +01:00
rodzic d4846ad7d0
commit 9efea5a966
4 zmienionych plików z 555 dodań i 138 usunięć

Wyświetl plik

@ -5,7 +5,6 @@ class PercentageBlurChecker:
def __init__(self, percentage): def __init__(self, percentage):
self.percentage = percentage self.percentage = percentage
self.cache = None self.cache = None
self.threshold = None
def NeedPreProcess(self): def NeedPreProcess(self):
return True return True
@ -15,7 +14,8 @@ class PercentageBlurChecker:
# Open video file # Open video file
cap = cv2.VideoCapture(video_path) cap = cv2.VideoCapture(video_path)
if (cap.isOpened() == False): if (cap.isOpened() == False):
raise Exception("Error opening video stream or file") print("Error opening video stream or file")
return
if start_frame is not None: if start_frame is not None:
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame) cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
@ -107,3 +107,83 @@ class SimilarityChecker:
self.last_image_features = cv2.goodFeaturesToTrack(image_bw, self.max_features, 0.01, 10) self.last_image_features = cv2.goodFeaturesToTrack(image_bw, self.max_features, 0.01, 10)
return distance, res, self.last_image_id return distance, res, self.last_image_id
class NaiveBlackFrameChecker:
def __init__(self, threshold):
self.threshold = threshold
def PreProcess(self, video_path, start_frame, end_frame, width=800, height=600):
return
def NeedPreProcess(self):
return False
def IsBlack(self, image_bw, id):
return np.average(image_bw) < self.threshold
class BlackFrameChecker:
def __init__(self, picture_black_ratio_th=0.98, pixel_black_th=0.30):
self.picture_black_ratio_th = picture_black_ratio_th if picture_black_ratio_th is not None else 0.98
self.pixel_black_th = pixel_black_th if pixel_black_th is not None else 0.30
self.luminance_minimum_value = None
self.luminance_range_size = None
self.absolute_threshold = None
def NeedPreProcess(self):
return True
def PreProcess(self, video_path, start_frame, end_frame, width=800, height=600):
# Open video file
cap = cv2.VideoCapture(video_path)
# Set frame start and end indices
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
frame_end = end_frame
if end_frame == -1:
frame_end = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# Initialize luminance range size and minimum value
self.luminance_range_size = 0
self.luminance_minimum_value = 255
frame_index = start_frame if start_frame is not None else 0
# Read and process frames from video file
while (cap.isOpened() and (end_frame is None or frame_index <= end_frame)):
ret, frame = cap.read()
if not ret:
break
# Resize frame to specified width and height
frame = cv2.resize(frame, (width, height))
# Convert frame to grayscale
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray_frame_min = gray_frame.min()
gray_frame_max = gray_frame.max()
# Update luminance range size and minimum value
self.luminance_range_size = max(self.luminance_range_size, gray_frame_max - gray_frame_min)
self.luminance_minimum_value = min(self.luminance_minimum_value, gray_frame_min)
frame_index += 1
# Calculate absolute threshold for considering a pixel "black"
self.absolute_threshold = self.luminance_minimum_value + self.pixel_black_th * self.luminance_range_size
# Close video file
cap.release()
def IsBlack(self, image_bw, id):
# Count number of pixels < self.absolute_threshold
nb_black_pixels = np.sum(image_bw < self.absolute_threshold)
# Calculate ratio of black pixels
ratio_black_pixels = nb_black_pixels / (image_bw.shape[0] * image_bw.shape[1])
# Check if ratio of black pixels is above threshold
return ratio_black_pixels >= self.picture_black_ratio_th

Wyświetl plik

@ -0,0 +1,141 @@
import argparse
import datetime
import os
class Parameters:
input = None
output = None
start = None
end = None
output_resolution = None
blur_percentage = None
blur_threshold = None
distance_threshold = None
black_ratio_threshold = None
pixel_black_threshold = None
use_srt = None
timezone = None
frame_format = None
stats_file = None
def __init__(self, args):
# "input" -> path to input video file(s), use ',' to separate multiple files")
# "output" -> path to output directory")
# "start" -> start frame index")
# "end" -> end frame index")
# "output-resolution" -> Override output resolution (ex. 640x480)")
# "blur-percentage" -> discard the lowest X percent of frames based on blur score (allowed values from 0.0 to 1.0)")
# "blur-threshold" -> blur measures that fall below this value will be considered 'blurry' (to be used in exclusion with --blur-percentage)")
# "distance-threshold" -> distance measures that fall below this value will be considered 'similar'")
# "black-ratio-threshold" -> Set the threshold for considering a frame 'black'. Express the minimum value for the ratio: nb_black_pixels / nb_pixels. Default value is 0.98")
# "pixel-black-threshold" -> Set the threshold for considering a pixel 'black'. The threshold expresses the maximum pixel luminance value for which a pixel is considered 'black'. Good value is 0.30 (30%)")
# "use-srt" -> Use SRT files for extracting metadata (same name as video file with .srt extension)")
# "timezone" -> UTC timezone offset (ex. -5 for EST). Default to local timezone")
# "frame-format" -> frame format (jpg, png, tiff, etc.)")
# "stats-file" -> Save statistics to csv file")
if (not self.ValidateParameters(args)):
print("Invalid parameters")
exit()
if not os.path.exists(args["output"]):
os.makedirs(args["output"])
self.input = args["input"].split(",")
self.output = args["output"]
self.start = args["start"] if args["start"] else 0
self.end = args["end"] if args["end"] else None
self.blur_percentage = args["blur_percentage"] if args["blur_percentage"] else None
self.blur_threshold = args["blur_threshold"] if args["blur_threshold"] else None
self.distance_threshold = args["distance_threshold"] if args["distance_threshold"] else None
self.black_ratio_threshold = args["black_ratio_threshold"] if args["black_ratio_threshold"] else None
self.pixel_black_threshold = args["pixel_black_threshold"] if args["pixel_black_threshold"] else None
self.use_srt = args["use_srt"]
self.utc_offset = datetime.timedelta(hours=int(args["timezone"])) if args["timezone"] != "local" else datetime.datetime.now() - datetime.datetime.utcnow()
self.frame_format = args["frame_format"]
self.output_resolution = tuple(map(int, args["output_resolution"].split("x"))) if args["output_resolution"] else None
self.stats_file = args["stats_file"] if args["stats_file"] else None
# We will resize the image to this size before processing
self.internal_width = 800
self.internal_height = 600
# Validate parameters
def ValidateParameters(self, args):
# input can be a list of files comma separated, check for each file
files = args["input"].split(",")
for file in files:
if not os.path.exists(file):
print("Input file does not exist: " + file)
return False
if not os.path.exists(args["output"]):
os.makedirs(args["output"])
if args["start"] and args["start"] < 0:
print("Start frame index must be greater than 0")
return False
if args["end"]:
if args["end"] < 0:
print("End frame index must be greater than 0")
return False
if args["end"] < args["start"]:
print("End frame index must be greater than start frame index")
return False
if args["timezone"] and args["timezone"] != "local":
try:
val = int(args["timezone"])
if val < -12 or val > 14:
print("Timezone must be in the range -12 to 14")
return False
except ValueError:
print("Timezone must be a valid integer")
return False
if args["blur_percentage"] and (args["blur_percentage"] < 0 or args["blur_percentage"] > 1):
print("Blur percentage must be in the range 0.0 to 1.0")
return False
if args["blur_threshold"] and args["blur_threshold"] < 0:
print("Blur threshold must be greater than 0")
return False
if args["distance_threshold"] and args["distance_threshold"] < 0:
print("Distance threshold must be greater than 0")
return False
if args["black_ratio_threshold"] and (args["black_ratio_threshold"] < 0 or args["black_ratio_threshold"] > 1):
print("Black ratio threshold must be in the range 0.0 to 1.0")
return False
if args["pixel_black_threshold"] and (args["pixel_black_threshold"] < 0 or args["pixel_black_threshold"] > 1):
print("Pixel black threshold must be in the range 0.0 to 1.0")
return False
if args["output_resolution"]:
segs = args["output_resolution"].split("x")
if (len(segs) != 2):
print("Output resolution must be in the format WxH")
return False
if (int(segs[0]) <= 0 or int(segs[1]) <= 0):
print("Output resolution must be in the format WxH")
return False
return True

Wyświetl plik

@ -0,0 +1,124 @@
from datetime import datetime
import re
class SrtFileParser:
def __init__(self, filename, utc_offset):
self.filename = filename
self.data = []
self.utc_offset = utc_offset
def get_entry(self, timestamp):
if not self.data:
self.parse()
for entry in self.data:
if entry["timestamp"] <= timestamp:
return entry
return None
def parse(self):
# The SRT file is formatted this way:
# 1
# 00:00:00,000 --> 00:00:00,016
# <font size="36">SrtCnt : 1, DiffTime : 16ms
# 2023-01-06 18:56:48,380,821
# [iso : 3200] [shutter : 1/60.0] [fnum : 280] [ev : 0] [ct : 3925] [color_md : default] [focal_len : 240] [latitude: 0.000000] [longitude: 0.000000] [altitude: 0.000000] </font>
with open(self.filename, 'r') as f:
for line in f:
# Check if line is empty
if not line.strip():
if srtcnt is not None:
self.data.append({
"srtcnt": srtcnt,
"difftime": difftime,
"timestamp": timestamp,
"iso": iso,
"shutter": shutter,
"fnum": fnum,
"ev": ev,
"ct": ct,
"color_md": color_md,
"focal_len": focal_len,
"latitude": latitude,
"longitude": longitude,
"altitude": altitude
})
srtcnt = None
difftime = None
timestamp = None
iso = None
shutter = None
fnum = None
ev = None
ct = None
color_md = None
focal_len = None
latitude = None
longitude = None
altitude = None
continue
# Remove the html font tag
line = re.sub('<[^<]+?>', '', line)
match = re.search("SrtCnt : (\d+)", line)
if match:
srtcnt = int(match.group(1))
match = re.search("DiffTime : (\d+)ms", line)
if match:
difftime = int(match.group(1))
match = re.search("(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3})", line)
if match:
timestamp = match.group(1)
timestamp = datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S,%f")
# The timestamp is in local time, so we need to subtract the UTC offset
timestamp = timestamp - self.utc_offset
match = re.search("iso : (\d+)", line)
if match:
iso = int(match.group(1))
match = re.search("shutter : (\d+/\d+.\d+)", line)
if match:
shutter = match.group(1)
match = re.search("fnum : (\d+)", line)
if match:
fnum = int(match.group(1))
match = re.search("ev : (\d+)", line)
if match:
ev = int(match.group(1))
match = re.search("ct : (\d+)", line)
if match:
ct = int(match.group(1))
match = re.search("color_md : (\w+)", line)
if match:
color_md = match.group(1)
match = re.search("focal_len : (\d+)", line)
if match:
focal_len = int(match.group(1))
match = re.search("latitude: (\d+.\d+)", line)
if match:
latitude = float(match.group(1))
match = re.search("longitude: (\d+.\d+)", line)
if match:
longitude = float(match.group(1))
match = re.search("altitude: (\d+.\d+)", line)
if match:
altitude = float(match.group(1))

Wyświetl plik

@ -1,51 +1,18 @@
import datetime
from math import floor from math import floor
import time import time
import cv2 import cv2
import os import os
from opendm.video.parameters import Parameters
from .checkers import PercentageBlurChecker, SimilarityChecker, ThresholdBlurChecker import pymediainfo
import collections
# Input parameters: from exif import Image, Orientation
# input = path to input video file from checkers import BlackFrameChecker, PercentageBlurChecker, SimilarityChecker, ThresholdBlurChecker
# output = path to output directory from srtparser import SrtFileParser
# start = start frame index
# end = end frame index
# output_resolution = Override output resolution (ex. 640x480)
# blur_percentage = discard the lowest X percent of frames based on blur score (allowed values from 0.0 to 1.0)
# blur_threshold = blur measures that fall below this value will be considered 'blurry' (to be used in exclusion with -bp)
# distance_threshold = distance measures that fall below this value will be considered 'similar'
# frame_format = frame format (jpg, png, tiff, etc.)
# stats_file = Save statistics to csv file
# internal_width = We will resize the image to this width before processing
# internal_height = We will resize the image to this height before processing
class Parameters:
def __init__(self):
self.input = None
self.output = None
self.start = 0
self.end = None
self.blur_percentage = None
self.blur_threshold = None
self.distance_threshold = None
self.frame_format = "jpg"
self.output_resolution = None
self.stats_file = None
# We will resize the image to this size before processing
self.internal_width = 800
self.internal_height = 600
class Video2Dataset: class Video2Dataset:
def __init__(self, parameters): def __init__(self, parameters: Parameters):
if not self.ValidateParameters(parameters):
raise Exception("Invalid parameters")
self.parameters = parameters self.parameters = parameters
# We prioritize blur threshold over blur percentage. # We prioritize blur threshold over blur percentage.
@ -58,82 +25,78 @@ class Video2Dataset:
self.blur_checker = None self.blur_checker = None
self.similarity_checker = SimilarityChecker(parameters.distance_threshold) if parameters.distance_threshold is not None else None self.similarity_checker = SimilarityChecker(parameters.distance_threshold) if parameters.distance_threshold is not None else None
self.black_checker = BlackFrameChecker(parameters.black_ratio_threshold, parameters.pixel_black_threshold) if parameters.black_ratio_threshold is not None or parameters.pixel_black_threshold is not None else None
self.frame_index = parameters.start self.frame_index = parameters.start
self.orientation = None
self.f = None self.f = None
# Validate parameters
def ValidateParameters(self, args):
if not os.path.exists(args.input):
print("Input file does not exist")
return False
if not os.path.exists(args.output):
os.makedirs(args.output)
if args.start and args.start < 0:
print("Start frame index must be greater than 0")
return False
if args.end:
if args.end < 0:
print("End frame index must be greater than 0")
return False
if args.end < args.start:
print("End frame index must be greater than start frame index")
return False
if args.blur_percentage and (args.blur_percentage < 0 or args.blur_percentage > 1):
print("Blur percentage must be in the range 0.0 to 1.0")
return False
if args.blur_threshold and args.blur_threshold < 0:
print("Blur threshold must be greater than 0")
return False
if args.distance_threshold and args.distance_threshold < 0:
print("Distance threshold must be greater than 0")
return False
if args.output_resolution:
segs = args.output_resolution.split("x")
if (len(segs) != 2):
print("Output resolution must be in the format WxH")
return False
if (int(segs[0]) <= 0 or int(segs[1]) <= 0):
print("Output resolution must be in the format WxH")
return False
return True
def ProcessVideo(self): def ProcessVideo(self):
start = time.time() start = time.time()
if (self.parameters.stats_file is not None):
self.f = open(self.parameters.stats_file, "w")
self.f.write("global_idx;file_name;frame_index;blur_score;is_blurry;is_black;last_frame_index;similarity_score;is_similar;written\n")
self.global_idx = 0
# foreach input file
for input_file in self.parameters.input:
# get file name
file_name = os.path.basename(input_file)
print("Processing video: {}".format(input_file))
if self.parameters.use_srt:
srt_file = os.path.splitext(input_file)[0] + ".srt"
if os.path.exists(srt_file):
print("Loading SRT file: {}".format(srt_file))
srt_parser = SrtFileParser(srt_file, self.parameters.utc_offset)
srt_parser.parse()
else:
srt_file = os.path.splitext(input_file)[0] + ".SRT"
if os.path.exists(srt_file):
print("Loading SRT file: {}".format(srt_file))
srt_parser = SrtFileParser(srt_file, self.parameters.utc_offset)
srt_parser.parse()
else:
print("SRT file not found: {}".format(srt_file))
srt_parser = None
else:
srt_parser = None
# get video info
video_info = self.GetVideoInfo(input_file)
print(video_info)
if (self.blur_checker is not None and self.blur_checker.NeedPreProcess()): if (self.blur_checker is not None and self.blur_checker.NeedPreProcess()):
print("Preprocessing video...") print("Preprocessing for blur checker...")
self.blur_checker.PreProcess(self.parameters.input, self.parameters.start, self.parameters.end, self.parameters.internal_width, self.parameters.internal_height) self.blur_checker.PreProcess(input_file, self.parameters.start, self.parameters.end, self.parameters.internal_width, self.parameters.internal_height)
end = time.time() end = time.time()
print("Preprocessing time: {:.2f}s".format(end - start)) print("Preprocessing time: {:.2f}s".format(end - start))
print("Calculated threshold is {}".format(self.blur_checker.threshold)) print("Calculated threshold is {}".format(self.blur_checker.threshold))
if (self.black_checker is not None and self.black_checker.NeedPreProcess()):
start2 = time.time()
print("Preprocessing for black checker...")
self.black_checker.PreProcess(input_file, self.parameters.start, self.parameters.end, self.parameters.internal_width, self.parameters.internal_height)
end = time.time()
print("Preprocessing time: {:.2f}s".format(end - start2))
print("Calculated luminance_range_size is {}".format(self.black_checker.luminance_range_size))
print("Calculated luminance_minimum_value is {}".format(self.black_checker.luminance_minimum_value))
print("Calculated absolute_threshold is {}".format(self.black_checker.absolute_threshold))
# open video file # open video file
cap = cv2.VideoCapture(self.parameters.input) cap = cv2.VideoCapture(input_file)
if (cap.isOpened() == False): if (not cap.isOpened()):
print("Error opening video stream or file") print("Error opening video stream or file")
return return
frames_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) frames_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
if (self.parameters.stats_file is not None):
self.f = open(self.parameters.stats_file, "w")
if (self.blur_checker is not None):
self.f.write("blur_threshold;{}\n\n".format(self.blur_checker.threshold).replace(".", ","))
self.f.write("frame_index;blur_score;is_blurry;last_frame_index;similarity_score;is_similar;written\n")
if (self.parameters.start is not None): if (self.parameters.start is not None):
cap.set(cv2.CAP_PROP_POS_FRAMES, self.parameters.start) cap.set(cv2.CAP_PROP_POS_FRAMES, self.parameters.start)
self.frame_index = self.parameters.start self.frame_index = self.parameters.start
@ -154,24 +117,25 @@ class Video2Dataset:
# Calculate progress percentage # Calculate progress percentage
progress = floor((self.frame_index - start_frame + 1) / frames_to_process * 100) progress = floor((self.frame_index - start_frame + 1) / frames_to_process * 100)
print("[{:3d}%] Processing frame {}/{}: ".format(progress, self.frame_index - start_frame + 1, frames_to_process), end="") print("[{}][{:3d}%] Processing frame {}/{}: ".format(file_name, progress, self.frame_index - start_frame + 1, frames_to_process), end="")
stats = self.ProcessFrame(frame) stats = self.ProcessFrame(frame, video_info, srt_parser)
if stats is not None and self.parameters.stats_file is not None: if stats is not None and self.parameters.stats_file is not None:
self.WriteStats(stats) self.WriteStats(input_file, stats)
cap.release() cap.release()
if (self.f is not None):
if self.f is not None:
self.f.close() self.f.close()
end = time.time() end = time.time()
print("Total processing time: {:.2f}s".format(end - start)) print("Total processing time: {:.2f}s".format(end - start))
def ProcessFrame(self, frame): def ProcessFrame(self, frame, video_info, srt_parser):
res = {"frame_index": self.frame_index} res = {"frame_index": self.frame_index, "global_idx": self.global_idx}
frame_bw = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) frame_bw = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame_bw = cv2.resize(frame_bw, (self.parameters.internal_width, self.parameters.internal_height)) frame_bw = cv2.resize(frame_bw, (self.parameters.internal_width, self.parameters.internal_height))
@ -186,6 +150,15 @@ class Video2Dataset:
self.frame_index += 1 self.frame_index += 1
return res return res
if (self.black_checker is not None):
is_black = self.black_checker.IsBlack(frame_bw, self.frame_index)
res["is_black"] = is_black
if is_black:
print ("black, skipping")
self.frame_index += 1
return res
if (self.similarity_checker is not None): if (self.similarity_checker is not None):
similarity_score, is_similar, last_frame_index = self.similarity_checker.IsSimilar(frame_bw, self.frame_index) similarity_score, is_similar, last_frame_index = self.similarity_checker.IsSimilar(frame_bw, self.frame_index)
res["similarity_score"] = similarity_score res["similarity_score"] = similarity_score
@ -197,27 +170,126 @@ class Video2Dataset:
self.frame_index += 1 self.frame_index += 1
return res return res
self.SaveFrame(frame) self.SaveFrame(frame, video_info, srt_parser)
res["written"] = True res["written"] = True
self.frame_index += 1 self.frame_index += 1
self.global_idx += 1
print ("saved") print ("saved")
return res return res
def SaveFrame(self, frame): def SaveFrame(self, frame, video_info, srt_parser: SrtFileParser):
if (self.parameters.output_resolution is not None): if (self.parameters.output_resolution is not None):
frame = cv2.resize(frame, self.parameters.output_resolution) frame = cv2.resize(frame, self.parameters.output_resolution)
cv2.imwrite(os.path.join(self.parameters.output, path = os.path.join(self.parameters.output,
"frame_{}.{}".format(self.frame_index, self.parameters.frame_format)), frame) "frame_{}_{}.{}".format(self.global_idx, self.frame_index, self.parameters.frame_format))
def WriteStats(self, stats): _, buf = cv2.imencode('.' + self.parameters.frame_format, frame)
self.f.write("{};{};{};{};{};{};{}\n".format(stats["frame_index"],
img = Image(buf.tobytes())
start_time = (video_info.start_time if video_info.start_time is not None \
else srt_parser.data[0].timestamp if srt_parser is not None \
else datetime.datetime.now()) + self.parameters.utc_offset
elapsed_time = start_time + datetime.timedelta(seconds=(self.frame_index / video_info.frame_rate))
# Set datetime_original
img.datetime_original = elapsed_time.strftime('%Y:%m:%d %H:%M:%S')
img.datetime_digitized = elapsed_time.strftime('%Y:%m:%d %H:%M:%S')
img.datetime = elapsed_time.strftime('%Y:%m:%d %H:%M:%S')
img.pixel_x_dimension = frame.shape[1]
img.pixel_y_dimension = frame.shape[0]
img.orientation = video_info.orientation if video_info.orientation is not None else Orientation.TOP_LEFT
img.software = "Video2Dataset"
if video_info.model is not None:
img.model = video_info.model
entry = srt_parser.get_entry(elapsed_time) if srt_parser is not None else None
if (entry is not None):
img.exposure_time = 1 / float(entry["shutter"].split("/")[1])
img.focal_length = entry["focal_len"]
img.f_number = entry["fnum"]
img.latitude = entry["latitude"]
img.longitude = entry["longitude"]
img.altitude = entry["altitude"]
img.photographic_sensitivity = entry["iso"]
with open(path, "wb") as f:
f.write(img.get_file())
def WriteStats(self, input_file, stats):
self.f.write("{};{};{};{};{};{};{};{};{};{}\n".format(
stats["global_idx"],
input_file,
stats["frame_index"],
stats["blur_score"] if "blur_score" in stats else "", stats["blur_score"] if "blur_score" in stats else "",
stats["is_blurry"] if "is_blurry" in stats else "", stats["is_blurry"] if "is_blurry" in stats else "",
stats["is_black"] if "is_black" in stats else "",
stats["last_frame_index"] if "last_frame_index" in stats else "", stats["last_frame_index"] if "last_frame_index" in stats else "",
stats["similarity_score"] if "similarity_score" in stats else "", stats["similarity_score"] if "similarity_score" in stats else "",
stats["is_similar"] if "is_similar" in stats else "", stats["is_similar"] if "is_similar" in stats else "",
stats["written"] if "written" in stats else "").replace(".", ",")) stats["written"] if "written" in stats else "").replace(".", ","))
def GetVideoInfo(self, input_file):
video = cv2.VideoCapture(input_file)
total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
frame_rate = video.get(cv2.CAP_PROP_FPS)
start_time, orientation, model = self.GetVideoMetadata(input_file)
video.release()
return collections.namedtuple("VideoInfo", ["total_frames", "frame_rate", "start_time", "orientation", "model"])(total_frames, frame_rate, start_time, orientation, model)
def GetVideoMetadata(self, input_file):
try:
metadata = pymediainfo.MediaInfo.parse(input_file).to_data()
start_time = None
orientation = Orientation.TOP_LEFT
performer = None
if metadata is not None and 'tracks' in metadata:
# Check if it is safe to access the first element of the tracks list
if len(metadata['tracks']) > 0:
start_time = metadata['tracks'][0].get('encoded_date') or \
metadata['tracks'][0].get('tagged_date') or \
metadata['tracks'][0].get('file_creation_date')
start_time = datetime.datetime.strptime(start_time, '%Z %Y-%m-%d %H:%M:%S')
performer = metadata['tracks'][0].get('performer')
# Check if it is safe to access the second element of the tracks list
if len(metadata['tracks']) > 1:
orientation = metadata['tracks'][1].get('rotation')
if orientation is not None:
orientation = int(float(orientation))
if orientation == 0:
orientation = Orientation.TOP_LEFT
elif orientation == 90:
orientation = Orientation.LEFT_BOTTOM
elif orientation == 180:
orientation = Orientation.BOTTOM_RIGHT
elif orientation == 270:
orientation = Orientation.RIGHT_TOP
return start_time, orientation, performer
except Exception as e:
return start_time, orientation, performer