兩個視頻左右拼接成一個視頻,且兩個視頻音頻都保留


背景

現在遇到了一個這樣的問題,有兩個視頻,分辨率大小一致,需要將兩個視頻左右拼接在一起,類似直播平台打PK時的那種,左邊是一個畫面,右邊是另一個畫面的場景。面對這樣的問題,我首先的做法是看一下ffmpeg是否有現成的命令,直接在一個畫布上放置兩個視頻。但是搜索了很久沒有找到滿意的結果,加上給我的時間比較短,所以我采取了簡單但是步驟比較多的方式解決了該問題。

技術

語言:python3.6

組件:opencv、ffmpeg

思路

1、首先使用opencv將兩個視頻全部圖片幀提取出來。

2、按照圖序兩兩圖片幀進行水平拼接合並,生成新的圖組。

3、將新的圖組壓縮成視頻。

4、將兩個視頻文件的音頻提取出來,並且按照兩個音軌合並成一個音頻。

5、將新圖組壓縮的視頻和新的音頻進行合並得到最終的視頻。

下面是按照這個思路,每步制作的過程。

過程

1、提取圖片幀(opencv)

使用opencv將視頻圖片幀按照順序提取出來

# =============================================================================
# opencv生成圖片序列
# =============================================================================
import cv2

# 寫圖片
def save_image(num, image):
    """Save the images.

    Args:
        num: serial number
        image: image resource

    Returns:
        None
    """
    image_path = 'images/video1/{}.jpg'.format(str(num))
    cv2.imwrite(image_path, image)


file_path = 'videos/demo1.mp4'
vc = cv2.VideoCapture(file_path)  # import video files

# determine whether to open normally
if vc.isOpened():
    ret, frame = vc.read()
else:
    ret = False

count = 1  # count the number of pictures
frame_interval = 30  # video frame count interval frequency
frame_interval_count = 0

# loop read video frame
while ret:
    ret, frame = vc.read()
    # store operation every time f frame
    # if frame_interval_count % frame_interval == 0:
    save_image(count, frame)
    print("num:" + str(count) + ", frame: " +
          str(frame_interval_count))
    count += 1
    frame_interval_count += 1
    # cv2.waitKey(1)

vc.release()

這樣獲取了兩個視頻的所有圖片幀,按照數字進行了編號。

2、合成新圖組(opencv)

現在需要把兩個圖組的每一個對應編號的圖進行水平拼接,代碼如下:

# =============================================================================
# 水平合成圖組
# =============================================================================
import cv2
import numpy as np

# 按照兩個圖組的最小值+1,作為循環的最大值邊界
for i in range(1,2225):
    img1 = cv2.imread('images/video1/{}.jpg'.format(i))
    img2 = cv2.imread('images/video2/{}.jpg'.format(i))
    
    # img1 = cv2.resize(img1, (720, 1280))
    # img2 = cv2.resize(img2, (720, 1280))
    
    # 核心代碼
    image = np.concatenate([img1, img2], axis=1)
    cv2.imwrite('images/result/{}.jpg'.format(i), image)

完成這一步就已經得到了水平拼接的所有圖片。

3、壓縮新圖組變成新視頻(opencv)

現在需要把圖組壓縮成視頻,要考慮到原始視頻的幀率,保持一致。

# =============================================================================
# 壓縮圖片為視頻
# =============================================================================
import cv2
import os
fourcc = cv2.VideoWriter_fourcc(*'XVID')

videoWriter = cv2.VideoWriter('videos/new.mp4', fourcc, 30, (1440,1280))
for i in range(1, 2225):                                    #有多少張圖片,從編號1到編號2224
    image_number = i
    if not os.path.exists('images/result/{}.jpg'.format(str(i))):
        continue
    img12 = cv2.imread('images/result/' + str(i) + '.jpg')
    #cv2.imshow('img', img12)
    #cv2.waitKey(1)
    videoWriter.write(img12)
videoWriter.release()

執行完上面的代碼,已經獲得了一個水平拼接好的視頻,但是沒有聲音,下面來制作音頻。

4、提取音頻、合並音頻(ffmpeg)

使用ffmpeg對素材視頻音頻提取

ffmpeg -i videos/demo1.mp4 -acodec pcm_s16le -f s16le -ac 1 -ar 16000 -f wav audio/demo1.wav
ffmpeg -i videos/demo2.mp4 -acodec pcm_s16le -f s16le -ac 1 -ar 16000 -f wav audio/demo2.wav

至於ffmpeg這條命令的參數說明就不多說了,音頻幾個基本參數

下面開始合並音頻

ffmpeg -y -i audio/demo1.wav -i audio/demo2.wav -filter_complex "[0:0][1:0] amix=inputs=2:duration=longest" -c:a libmp3lame audio/new.mp3

別問為什么2個wav為啥要合並成一個mp3,這個完全看心情。

5、將新音頻壓縮至新視頻(ffmpeg)

使用ffmpeg進行壓縮

ffmpeg -i videos/new.mp4 -i audio/new.mp3 -map 0:v -map 1:a -c copy -shortest videos/final.mp4

得到最終視頻。

 

后記

這篇文章給的方法一定不是解決這個問題最優的方法,只是我對ffmpeg研究很淺,無法立馬寫出對應指令,如果有對ffmpeg研究很深的兄弟,可以留言提供那個最優解決方案。本篇文章,只是參考,希望給碰到相同問題的朋友提供一種解決方案。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM