效果图
简单来说,当一个高 FPS 的视频压缩为较低 FPS 的视频时,会选择某些帧作为关键帧插入。
B 站提供了 30fps 或 60fps 的视频。
因此,我们可以创建一个 120fps 的视频,然后在第1+4n 帧
插入你希望在 30fps 下显示的内容,其余帧则插入你希望在 60fps 下显示的内容。
这样,在阿 b 二压后,30fps 和 60fps 的视频就会显示不同的画面。
至于“1+4n”这个公式的由来。
可以首先制作一个每帧都标有序号的 120fps 视频。然后使用 ffmpeg 将视频转换为 30fps ,观察哪些帧被保留,从而确定关键帧。
proof of concept
懒得传 gist 了
import cv2
class Fps120FrameReader:
def __init__(self, filename):
self.src = cv2.VideoCapture(filename)
self.framerate = int(self.src.get(cv2.CAP_PROP_FPS))
if self.framerate not in [30,60,120]:
raise Exception(f"not support frame rate other than 30, 60, 120, framerate {self.framerate}")
self.current_frame = 0
self.frame = None
def read(self):
if self.current_frame % (120 // self.framerate) == 0:
ok, self.frame = self.src.read()
if not ok:
self.frame = None
self.current_frame +=1
return self.frame
def close(self):
return self.src.release()
@property
def size(self):
return int(self.src.get(cv2.CAP_PROP_FRAME_WIDTH)),int(self.src.get(cv2.CAP_PROP_FRAME_HEIGHT))
readerA = Fps120FrameReader('igotsmoke.mp4')
readerB = Fps120FrameReader('benkui.mp4')
assert readerA.size == readerB.size
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_video_C.mp4', fourcc, 120, readerA.size)
frame_count = 0
while True:
frameA = readerA.read()
frameB = readerB.read()
if frameA is None or frameB is None:
break
if frame_count % 4 == 1:
out.write(frameA)
else:
out.write(frameB)
frame_count += 1
readerA.close()
readerB.close()
out.release()
print("ok")
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.