百萬點贊怎麼來?Python批量製作抖音的卡點視訊原來這麼簡單!

程式設計師啟航發表於2019-07-18

1

目 標 場 景

玩抖音的朋友都應該知道,最近「 卡點視訊 」簡直不要太火。抖音上很多大神也出了剪輯各種卡點視訊的教程。

實際上,利用很多手機 APP 或者 PR、FCPX 軟體也可以製作卡點視訊,但是剪輯效率都太慢。如果想實現一籃子剪輯素材,通過執行一段程式碼,得到一個卡點視訊,這種感覺不要太爽。

本篇文章的目的是利用 Python 從一籃子素材中快速地剪輯卡點小視訊這一操作。

2

準 備 工 作

首先,對視訊的剪輯需要用到「 opencv 」庫,通過 pip3 安裝到虛擬環境中。

# opencv 用於剪輯視訊
pip3 install opencv-python

然而,通過 opencv 剪輯的視訊只有畫面,沒有背景音樂。

我們需要藉助「 ffmpeg 」,將抖音下載好的某個卡點視訊利用 ffmpeg 命令分離出音訊檔案,然後合併到上面剪輯的視訊當中。Python學習q-u-n七八四,七五八,二一四教程視訊,工具,各類實戰操作分享

# 分離BGM、合併視訊和BGM
pip3 install ffmpeg

3

編 寫 腳 本

我們以抖音上的某個卡點音樂為例,這段背景音樂的節奏需要一個 2s 的視訊,然後其他都是靜態圖片,每個圖片顯示 0.5s。

百萬點贊怎麼來?Python批量製作抖音的卡點視訊原來這麼簡單!

下面通過 5 個步驟完成卡點視訊的剪輯,分別是:剪輯開始視訊、合併靜態圖片視訊、合併上面兩段視訊、給視訊加入水印、加入背景音樂。

第一步,我們需要從視訊素材檔案中剪輯一段 2s 的片段。

通過 cv2 庫為視訊檔案構建一個「 VideoCapture 」物件,然後獲取到視訊的幀率和視訊的解析度。

# 視訊源
videoCapture = cv2.VideoCapture(soure_filename)
# 獲取視訊的幀率
fps = videoCapture.get(cv2.CAP_PROP_FPS)
# 獲取視訊的解析度
img_size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
                int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))

然後,利用上面的幀率、解析度構建一個寫入物件,即:「 VideoWriter 」。

# 構建一個視訊寫入物件
video_writer = cv2.VideoWriter(output_filename, cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'), fps, img_size)

最後,通過傳入要開始剪輯的起始點和要剪的長度,然後迴圈讀取視訊幀,如果滿足條件,就寫入到目標視訊檔案中。

寫入視訊幀完成之後,需要手動釋放物件資源。

# 開始幀和結束幀
start_frame = fps * start_time
end_frame = start_frame + peroid * fps
# 迴圈讀取視訊幀,只寫入開始幀和結束幀之間的幀資料
while True:
      success, frame = videoCapture.read()  
      if success:
            i += 1
            if start_frame <= i <= end_frame:
                # 將擷取到的畫面寫入“新視訊”
                video_writer.write(frame)
      else:
            break
# 釋放資源
videoCapture.release()

第二步,需要把所有的靜態檔案都合成一段視訊。

ps: 為了保證每一張****靜態圖片都顯示 0.5s,並且靜態圖片生成的視訊與第一段視訊使用同一幀率,因此我們應該針對每一張圖片寫入多次,即多幀資料。****每張圖片寫入的總次數為上段視訊的幀率的 1/2。

和剪輯視訊類似,靜態圖片合成視訊也需要先構建一個寫入物件 VideoWriter,然後通過向上取整獲取要寫入的總幀數。

# 視訊格式:MP4
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
# 構建寫入物件
video = cv2.VideoWriter(output_video_path, fourcc, fps, img_size)
# 每一張圖片要寫入的幀數目
total_count = math.ceil(fps / 2)

另外需要注意的是, 為了保證圖片合成的視訊能與第一段視訊順利剪輯在一起,這裡需要對圖片的解析度進行縮放,沒有畫素的位置填充為黑色。

def resize_image(target_image_path, target_size):
    """
    調整圖片大小,缺失的部分用黑色填充
    :param target_image_path: 圖片路徑
    :param target_size: 解析度大小
    :return:
    """
    image = Image.open(target_image_path)
    iw, ih = image.size  # 原始影象的尺寸
    w, h = target_size  # 目標影象的尺寸
    scale = min(w / iw, h / ih)  # 轉換的最小比例
    # 保證長或寬,至少一個符合目標影象的尺寸
    nw = int(iw * scale)
    nh = int(ih * scale)
    image = image.resize((nw, nh), Image.BICUBIC)  # 縮小影象
    # image.show()
    new_image = Image.new('RGB', target_size, (0, 0, 0, 0))  # 生成黑色影象
    # 將影象填充為中間影象,兩側為灰色的樣式    
    new_image.paste(image, ((w - nw) // 2, (h - nh) // 2))  
    # 覆蓋原圖片
    new_image.save(target_image_path)

圖片解析度處理完成之後,最後就可以讀取指定資料夾下的圖片,按照上面獲取的次數把靜態圖片寫入到視訊檔案中。

# 使用opencv讀取影象
frame = cv2.imread(image_path)
# 直接縮放到指定大小
frame_suitable = cv2.resize(frame, (img_size[0], img_size[1]), interpolation=cv2.INTER_CUBIC)
# 把圖片寫進視訊
# 重複寫入多少次
count = 0
while count < total_count:
       video.write(frame_suitable)
       count += 1

以上兩步已經完成了兩段單獨視訊的剪輯,第三步是「 合成 」上面的兩段視訊。

由於兩段視訊的幀率、解析度都一致,這裡不需要做其他多餘的處理,只需要遍歷兩段視訊檔案,迴圈讀取每一幀,然後寫入到新的視訊檔案中。

第四步,需要對視訊新增「 水印 」操作。

新增水印也很方便,利用 cv2 中的函式 putText,指定水印的起始座標、字型樣式、字型大小和顏色,然後迴圈每一幀,寫入到視訊就可以實現。

ret, frame = cap.read()
while ret:
     # 文字在圖中的座標(注意:這裡的座標原點是圖片左上角)
     x, y = img_size[0] - 200, img_size[1] - 50
     # 寫入水印文字,文字顏色為白色
     cv2.putText(img=frame, text=mask_word,
                    org=(x, y), fontFace=cv2.FONT_HERSHEY_COMPLEX_SMALL,
                    fontScale=1, color=(255, 255, 255))
     video_writer.write(frame)
     ret, frame = cap.read()
# 刪除原始檔,並重新命名臨時檔案
os.remove(video_path)
os.rename(video_temp_path, video_path)
print('水印新增完成~')
video_writer.release()
cap.release()

最後一步就是合成視訊和背景音樂,重新生成一段視訊檔案。

利用視訊的幀率與總幀數得到視訊的總時長, 然後利用 ffmpeg 命令對背景音樂做一次裁剪操作,使得視訊的長度與背景音樂的時間長度一致。

#獲取視訊的長度
cap = cv2.VideoCapture(video_path)
#幀率
fps = cap.get(cv2.CAP_PROP_FPS)
#總幀數
frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
#視訊總時長-秒,這裡做取整操作 【浮點型別】
time_count = math.floor(frame_count / fps)
print('幀率:%f,總幀數:%d' % (fps, frame_count))
print(time_count)
# 3.擷取音訊
# 為了簡單,這裡一般不會超過一分鐘
bgm_temp_path = get_temp_path(bgm_path, 'temp_new')
os.system('ffmpeg -i %s -ss 00:00:00 -t 00:00:%d -acodec copy %s' % (bgm_path, time_count, bgm_temp_path))

接著使用 ffmpeg 命令,合併視訊檔案和音訊檔案,就可以生成一個我們需要的卡點視訊。Python學習q-u-n七八四,七五八,二一四教程視訊,工具,各類實戰操作分享

#視訊、音訊合二為一
# 臨時檔案
video_temp_path = get_temp_path(video_path, 'temp')
os.system('ffmpeg -i %s  -i %s  -vcodec copy -acodec copy %s' % (video_path, bgm_path, video_temp_path))
# 刪除原始檔,重命令臨時檔案
os.remove(video_path)
os.rename(video_temp_path, video_path)

4

結 果 結 論

執行程式後,視訊、圖片、背景音樂會自動進行剪輯、合成,最後加上水印,在本地生成一個卡點視訊。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913713/viewspace-2650990/,如需轉載,請註明出處,否則將追究法律責任。

相關文章