I originally tried holding the thumbnails in memory, but that didn't work and now I'm creating temporary thumbnail files in a nearby directory. Anyway, the image creation works for photos, but it's failing for mp4 video and I'm not sure why. This is the error:
'D:\\Stuff\\Pictures\\Transit\\20230729_020700.mp4'
'D:\\Stuff\\Pictures\\Transit\\thumbs\\20230729_020700.mp4'
{'name': '20230729_020700', 'ext': 'mp4', 'name_ext': '20230729_020700.mp4', 'type': 'movie', 'dtime': '20230729_140700', 'width': 1920, 'height': 1080}
Traceback (most recent call last):
File "C:\stuff\Working\htdocs\PSSort\picsort\main.py", line 179, in <module>
list_dest_dir()
File "C:\stuff\Working\htdocs\PSSort\picsort\main.py", line 108, in list_dest_dir
this_file = get_file_deets(file)
^^^^^^^^^^^^^^^^^^^^
File "C:\stuff\Working\htdocs\PSSort\picsort\main.py", line 71, in get_file_deets
cv2.imwrite(thumb_path,frame)
cv2.error: OpenCV(4.8.1) D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:696: error: (-2:Unspecified error) could not find a writer for the specified extension in function 'cv::imwrite_'
In my code, I've put prints to show that the input file and output file names and paths are correct AND have the extension (which I stress because every post I could find on this error was always because someone forgot the extension). So what do I do when the extension is fine?
Code is below:
#input a filename. Something.jpg, thisisamov.mp4, etc.
#output adds an entry
def get_file_deets(name):
if settings['dest_dir'][-1] == '\\':
full_path_filename = settings['dest_dir']+name
thumb_path = settings['dest_dir']+'thumbs\\'+name
else:
full_path_filename = settings['dest_dir']+'\\'+name
thumb_path = settings['dest_dir']+'\\thumbs\\'+name
pre_r(full_path_filename)
pre_r(thumb_path)
temp = {}
temp['name'], temp['ext'] = name.rsplit('.')
# keep track of the whole name
temp['name_ext'] = name
if temp['ext'] != 'mp4':
image = Image.open(full_path_filename)
temp['type'] = 'image'
# Grab it's "taken on" date
exif = image.getexif();
temp['dtime'] = exif.get(306).replace(":", "").replace(' ','_')
temp['width'],temp['height'] = image.size
# first make a thumbnail, then B64 THAT (not the whole image)
image.thumbnail((100,100))
image.save(thumb_path)
image.close()
else:
temp['type'] = 'movie'
temp['dtime'] = datetime.fromtimestamp(os.path.getmtime(full_path_filename)).strftime("%Y%m%d %H%M%S").replace(' ','_')
probe = ffmpeg.probe(full_path_filename)
video_streams = [stream for stream in probe["streams"] if stream["codec_type"] == "video"][0]
temp['width'], temp['height'] = video_streams['width'], video_streams['height']
pre_r(temp)
# Time in seconds where you want to capture the thumbnail (e.g., 10 seconds)
thumbnail_time = 10
cap = cv2.VideoCapture(full_path_filename)
cap.set(cv2.CAP_PROP_POS_MSEC, thumbnail_time * 1000)
ret, frame = cap.read()
if ret:
cv2.imwrite(thumb_path,frame)
cap.release()
temp['size'] = f"{os.path.getsize(full_path_filename)/1000000:.2f}MBs"
return temp
Bonus: I'd love to know a cleaner way to do that if statement at the beginning. I toyed with a ternary, but it was ugly so I gave up on that.
Ok, I went over this again and realized that I'm trying to save a thumbnail as an mp4 which is obviously wrong. I want a THUMBNAIL... ergo a photo. I altered the code to make the thumbnail path the filename_vid.jpg and it works flawlessly.