首页 > 解决方案 > 如何将视频转 n 度

问题描述

我有一个需要旋转 n 度的视频(不仅仅是 90 或 180,我可以使用 ffmpeg 进行旋转,例如 1 或 10)。怎么能做到这一点?

我用谷歌搜索过,似乎没有这样的工具可以免费获得。

标签: pythonvideo

解决方案


我已经找到了一种不太优雅的方法,但它对我有用,所以我想分享它。

首先,我根据 learnopencv.com 的代码扭曲了视频:

# source learnopencv.com

import numpy as np
import cv2
from tqdm import tqdm

def fixBorder(frame):
    s = frame.shape
    # Scale the image 4% without moving the center
    T = cv2.getRotationMatrix2D((s[1] / 2, s[0] / 2), 0, 1.04)
    frame = cv2.warpAffine(frame, T, (s[1], s[0]))
    return frame

def straighten_vid(input_name, output_name, d_dx=0, d_dy=0, d_da=0):
    d_da *= np.pi / 180.
    # Read input video

    cp = cv2.VideoCapture(input_name)

    # To get number of frames
    n_frames = int(cp.get(cv2.CAP_PROP_FRAME_COUNT))

    # To check the number of frames in the video

    width = int(cp.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cp.get(cv2.CAP_PROP_FRAME_HEIGHT))


    # get the number of frames per second
    fps = cp.get(cv2.CAP_PROP_FPS)

    # Try doing 2*width
    out = cv2.VideoWriter(output_name, 0x7634706d, fps, (width, height))

    transforms_smooth = np.zeros((n_frames - 1, 3), np.float32)
    for i in tqdm(range(n_frames - 2)):
        transforms_smooth[i] = [d_dx, d_dy, d_da]

    # Reset stream to first frame
    cp.set(cv2.CAP_PROP_POS_FRAMES, 0)
    # Write n_frames-1 transformed frames
    for i in range(n_frames - 2):
        # Read next frame
        success, frame = cp.read()
        if not success:
            break

        # Extract transformations from the new transformation array
        dx = transforms_smooth[i, 0]
        dy = transforms_smooth[i, 1]
        da = transforms_smooth[i, 2]


        # Reconstruct transformation matrix accordingly to new values
        m = np.zeros((2, 3), np.float32)
        m[0, 0] = np.cos(da)
        m[0, 1] = -np.sin(da)
        m[1, 0] = np.sin(da)
        m[1, 1] = np.cos(da)
        m[0, 2] = dx
        m[1, 2] = dy

        # Apply affine wrapping to the given frame
        frame_stabilized = cv2.warpAffine(frame, m, (width, height))

        # Fix border artifacts
        frame_stabilized = fixBorder(frame_stabilized)

        # Write the frame to the file
        frame_out = frame_stabilized  #cv2.hconcat([frame, frame_stabilized])

        # If the image is too big, resize it.
        if (frame_out.shape[1] > 1920):
            frame_out = cv2.resize(frame_out, (frame_out.shape[1] // 2, frame_out.shape[0] // 2))

        # cv2.imshow("Before and After", frame_out)
        # cv2.waitKey(10)
        out.write(frame_out)

    # Release video
    cp.release()
    out.release()
    # Close windows
    cv2.destroyAllWindows()

d_da 是转动的角度,d_dx 和 d_dy 用于使视频居中。但是,这会留下一个没有声音的文件。要重新添加它,我这样做:

import moviepy.editor as mpe

input_folder = "my_folder\\my_folder\\" 
file_name = "my_file_name.MOV"
input_file = input_folder + file_name
output_file = input_folder + file_name.replace(".MOV", "_straightened.MOV")
output_file_final = input_folder + file_name.replace(".MOV", "_straightened_with_sound.mp4")
straighten_vid(input_file, output_file, 0, -70, 0.1)
my_clip = mpe.VideoFileClip(output_file)
audio_background = mpe.VideoFileClip(input_file).audio
final_clip = my_clip.set_audio(audio_background)
final_clip.write_videofile(output_file_final)

推荐阅读