いろいろダウンロードした動画ファイルを手動で分類するのがめんどくさくなったので、Pythonで作ろうとしたらドはまりしたので、備忘録的に記録しておきます。そうそう似たようなミスする人も少ないとは思いますが。
下記コードが一応の完成品。雑に組んでいるので力技や無駄がそこそこあります。
この時点でのプログラムの目的は、使っているのFireTVにキャストすると再生時に止まったりカクついたりする高いデータ速度(概ね5500kbps以上)のファイルを別フォルダに避けるだけのものです。
OpenVC2にデータ速度のプロパティ取得の方法が無かったようなので、比較的近しい値が出るのでビットレートを取得してそれを基準にしています。
OpenCV2を使っているのは参照したサイトがOpenCV2だっただけです…。
import cv2
import os
import shutil
import random
import time
check_dir = '/check_folder1'
hd_dir = '/hd_movie' #分類先フォルダ
#ファイル移動用関数。同名ファイルが有る場合はランダムな数値を付けて上書きしないようにする。
def filemove(file,dst_dir):
dst_file = dst_dir
#ディレクトリの有無を判別して、なければ作成
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
#同名ファイルがあるかないかを判別し、あったらファイル名に乱数を付与
if os.path.exists(os.path.join(dst_dir, os.path.basename(file))):
f_name , ext_name = os.path.basename(file).split('.')
random.seed(time.time())
new_file = f"{f_name}_{random.randint(1, 6000)}.{ext_name}"
dst_file = os.path.join(dst_dir, new_file)
shutil.move(file, dst_file) #ファイルの移動
time.sleep(3) #念のための小休止
#ファイルリストの取得
files = os.listdir(check_dir)
#各ファイルの判別
for file in files:
#MP4ファイルのみ判定
if not(file.endswith('.mp4')):
continue
#ファイルをOpenCV2で読み込む
cap = cv2.VideoCapture(os.path.join(check_dir, file))
#フレーム幅の取得
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
#フレーム高の取得
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
#ビットレートの取得
bitrate = cap.get(cv2.CAP_PROP_BITRATE)
print(f"File: {file}, Width: {width}, Height: {height}, Bitrate: {bitrate}")
#再生時間の計算(後々再生時間でも分別するのに利用)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
fps = cap.get(cv2.CAP_PROP_FPS)
movie_time = frame_count // fps
print(f"movie_time:{movie_time}sec")
#再生時間の整形
movie_hour = 0
movie_min = 0
movie_sec = movie_time
if movie_time > 60:
movie_min = int(movie_time / 60)
movie_sec = movie_time % 60
if movie_min > 60:
movie_hour = int(movie_min / 60)
movie_min = movie_min % 60
print(f"movie_time:{movie_hour}:{movie_min}:{movie_sec}")
cap.release()
#高ビットレート判定し、高ビットレートなら指定フォルダへ移動
if bitrate > 5500:
print('--> High Bitrate, Move to movie folder')
filemove(os.path.join(check_dir, file), hd_dir)
exit()
当初作ったときはshutil.move()でプロセスエラーだかパーミッションエラーだかが出てコピーまでは出来るけど、元データが残ったままでした。
原因はOpenCV2のrelease()でした。
OpenCV2の使い方を結構適当に見ていたのと、ググったところで出てきたのがカメラからの取り込み説明が多かったりしたので、このファイルを閉じるという動作が見当たりませんでした。
shutilライブラリのmoveが悪いのかと思ってcopy2にして削除コマンド入れたり、osライブラリのリネームを使おうとしたりしたものの改善せず。
ディレクトリが開いたままだから駄目なのかと思ったら、そもそも閉じる必要が無かったりと、ぐるぐる原因がわからずでした。
それで数日放置して、OpenCV2で情報取得したファイルの方に気がついて、調べてようやく解決。
ちゃんと使い方を把握しないと要らないところでハマるので、ライブラリを使うときはちゃんと調べましょう。
特にファイル関連は。