python根據達芬奇場景分析儲存的edl檔案,智慧裁切輸出4K影片畫面(不帶聲音)-自動找到MP4對應的EDL檔案並移動到指定目錄下對應的秒數資料夾下-只處理大於5幀的剪下點的畫面

大话人生發表於2024-03-29

使用前先將mp4對應的EDL檔案命名為相同的名字,如:春天.mp4, 春天.edl

只處理持續時間大於5幀的畫面

import cv2
import os
import time
import datetime
import shutil
from moviepy.editor import VideoFileClip



#讀取切分檔案
def readQiFenWenJian(filename):
    with open(filename, "r", encoding='UTF-8')as f:
        res_list = f.readlines()
        print("讀取到的切分檔案")

        print(res_list)
        print(len(res_list))
    zuizhong_res_list = []
    for i in range(2,len(res_list)):
        if res_list[i] != '\n':
            zuizhong_res_list.append(res_list[i])

    print(zuizhong_res_list)
    print(len(zuizhong_res_list))
    return zuizhong_res_list



# 讀取一個影片檔案,從幀列表中,開始算後續幀,第一個幀尾為0
def handleOneVideo(video_file,zhen_list):
    #獲取當前時間
    nowtime = time.strftime('%Y%m%d%H%M%S', time.localtime())
    #建立影片檔案目錄
    xinjianmulu = str(video_file).replace(".mp4","")
    createDir(file_dir=xinjianmulu)

    for i in range(0, len(zhen_list)):
        print("進入for迴圈")
        yihang_shifenmiao = []
        yihangshuju = zhen_list[i]
        print("一行資料:")
        print(yihangshuju)
        yihang_list = yihangshuju.split(" ")
        print("yihang列表:")
        print(yihang_list)
        for one in yihang_list:
            if ":" in one:
                yihang_shifenmiao.append(one)

        print("yihang時分秒幀-列表:")
        print(yihang_shifenmiao)
        start_shifenmiao = yihang_shifenmiao[0]
        start_shifenmiao_list = start_shifenmiao.split(":")
        print("start_shifenmiao_list:")
        print(start_shifenmiao_list)

        end_shifenmiao = yihang_shifenmiao[1]
        end_shifenmiao_list = end_shifenmiao.split(":")
        print("end_shifenmiao_list:")
        print(end_shifenmiao_list)


        START_HOUR = int(start_shifenmiao_list[0])  # 開始小時
        START_MIN = int(start_shifenmiao_list[1])  # 開始分鐘
        START_SECOND = int(start_shifenmiao_list[2])  # 開始秒數
        START_TIME = START_HOUR * 3600 + START_MIN * 60 + START_SECOND  # 設定開始時間(單位秒)
        END_HOUR = int(end_shifenmiao_list[0])  # 結束小時
        END_MIN = int(end_shifenmiao_list[1])  # 結束分鐘
        END_SECOND = int(end_shifenmiao_list[2])   # 結束秒
        END_TIME = END_HOUR * 3600 + END_MIN * 60 + END_SECOND  # 設定結束時間(單位秒)

        video = video_file
        cap = cv2.VideoCapture(video)  # 讀取影片
        FPS = cap.get(cv2.CAP_PROP_FPS)
        print("幀率:")
        print(FPS)

        size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
        print("大小:")
        print(size)

        TOTAL_FRAME = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 獲取影片總幀數
        print("總幀數:")
        print(TOTAL_FRAME)
        frameToStart = START_TIME * FPS+int(start_shifenmiao_list[3])  # 開始幀 = 開始時間*幀率 + 多餘幀   根據達芬奇切割點自動算出開始幀
        print("開始幀:")
        print(frameToStart)
        frametoStop = END_TIME * FPS + int(end_shifenmiao_list[3])  # 結束幀 = 結束時間*幀率 + 多餘幀 根據達芬奇切割點自動算出開始幀
        print("結束幀:")
        print(frametoStop)
        cishu = i
        zhenchazhi = int(frametoStop-frameToStart)
        #如果結束幀和開始幀相差大於5幀才進行處理
        if zhenchazhi>=5:

            xierushipin = r'%s_%s.mp4' % (video, cishu)
            print("開始寫入%s檔案"%xierushipin)
            # 分批寫入影片檔案
            videoWriter = cv2.VideoWriter(
                xierushipin, cv2.VideoWriter_fourcc(*'mp4v'), FPS, size)

            cap.set(cv2.CAP_PROP_POS_FRAMES, frameToStart)  # 設定讀取的位置,從第幾幀開始讀取影片
            #如果是第0幀,則寫入,如果不是從第0幀開始的,就往後推移一幀
            # if frameToStart==0:
            #     COUNT = frameToStart
            # else:
            #     COUNT = frameToStart + 1,

            COUNT = frameToStart
            chushi = COUNT
            #定義個全域性變數
            global biaozhishuzhi
            biaozhishuzhi=True
            while biaozhishuzhi:
                print("進入while迴圈")
                success, frame = cap.read()
                if success:
                    COUNT += 1
                    if COUNT <= frametoStop and COUNT > frameToStart:  # 選取起始幀
                        print('correct= ', COUNT)
                        videoWriter.write(frame)
                # print('mistake= ', COUNT)
                if COUNT > frametoStop:
                    break
                if i+2 >len(zhen_list):
                    biaozhishuzhi=False
                print("退出while迴圈")

            print("迴圈標誌:%s" % str(biaozhishuzhi))

            videoWriter.release()  #釋放寫入
            #獲取檔案時長,並移動檔案到指定目錄下的對應的秒數的目錄下,
            getTimeAndMoveToMiao(filename=xierushipin, yidongdaogenmulu=xinjianmulu)

            print("寫入%s檔案完成" % xierushipin)
            jieshu = COUNT
            jilu = '第%s次剪下點,剪下開始%s到結束%s結束\n' % (str(i), str(chushi), str(jieshu))
            print(jilu)
            with open(r'%s_%s_jilu.txt' % (video_file, nowtime), 'a+', encoding='utf-8') as f:
                f.write(jilu)
        else:
            miaoshu = '第%s次剪下點,結束幀%s和開始幀%s相差%s小於5幀,不進行處理\n' %(str(i),str(frametoStop),str(frameToStart),str(zhenchazhi))
            print(miaoshu)
            with open(r'%s_%s_jilu.txt' % (video_file, nowtime), 'a+', encoding='utf-8') as f:
                f.write(miaoshu)

    print("退出for迴圈")

#獲取指定資料夾下所有MP4檔案的時長
def getFileNames(path,houzui=".mp4"):
    return [os.path.join(path,f) for f in os.listdir(path) if f.endswith(houzui)]

#如果不存在就建立
def createDir(file_dir):
    # 如果不存在資料夾,就建立
    if not os.path.isdir(file_dir):
        os.mkdir(file_dir)

#獲取影片時長
def getTimeLong(videoFile):

    clip = VideoFileClip(videoFile)
    sicahng = clip.duration
    print(sicahng) # seconds
    clip.close()
    return sicahng
#移動檔案到指定資料夾下的yiqiege目錄
def moveFile(zhidingmulu,file_path):
    try:
        # 移動檔案到資料夾目錄中
        shutil.move(file_path, zhidingmulu)
        print("移動檔案%s到已切割資料夾" % file_path)
    except Exception as e:
        print("移動出錯:%s" % str(e))

#讀取檔案時長,並移動到對應秒數的資料夾中
def getTimeAndMoveToMiao(filename,yidongdaogenmulu):
    #檔案
    one = filename

    path = yidongdaogenmulu
    try:
        one_shichang = getTimeLong(one)
        print("%s檔案的時長為 %s 秒"%(one,one_shichang))
        zhengshu = int(one_shichang)
        zhengshijia1 = zhengshu+1
        #移動到指定時間的資料夾
        xiaoyu1miao = "%s/大於%s秒小於%s秒"% (path,str(zhengshu),str(zhengshijia1))
        createDir(file_dir=xiaoyu1miao)
        moveFile(zhidingmulu=xiaoyu1miao, file_path=one)

    except Exception as e:
        print("%s檔案的時長失敗,原因:%s"%(one,str(e)))
        #移動到指定時間的資料夾
        jieshishibai = "%s/解析失敗"% path
        createDir(file_dir=jieshishibai)
        moveFile(zhidingmulu=jieshishibai, file_path=one)


if __name__ == '__main__':
    a=datetime.datetime.now()
    startime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    genmulu = r"C:\4k\ceshi\daichuli"
    file_list = getFileNames(path=genmulu,houzui=".mp4")
    for one_file in file_list:
        print("處理%s檔案"% str(one_file))
        video_file=one_file  #mp4檔案
        qiefenwenjian = str(video_file).replace(".mp4",".edl")
        zhen_list = readQiFenWenJian(filename=qiefenwenjian)
        print("處理MP4影片檔案:%s" % one_file)
        print("對應的edl檔案:%s" % qiefenwenjian)
        handleOneVideo(video_file, zhen_list)
    b = datetime.datetime.now()
    endtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    cha = (b-a).seconds #時間差的計算,單位為秒
    print("程式開始執行時間:")
    print(startime)
    print("程式結束執行時間:")
    print(endtime)
    print("耗時:")
    print(cha)
    print("")

相關文章