如何用Python实现流畅全屏视频播放并同步执行代码
解决Python视频全屏播放卡顿、画面裁剪及同步执行代码问题
问题根源
- 画面裁剪:cv2的
cv2.namedWindow默认拉伸画面,未保持视频原比例;moviepy的preview逻辑未做比例适配,导致画面边缘被裁切。 - 播放卡顿:单线程环境下视频渲染与代码执行互相阻塞,且cv2的
waitKey帧率控制精度不足。 - 同步执行:默认视频播放为阻塞式逻辑,必须通过多线程/多进程分离播放与业务代码。
解决方案(cv2+多线程)
核心思路
- 获取屏幕分辨率,计算视频适配后的全屏尺寸(保持原比例,用黑边填充空白区域)
- 用多线程分离视频播放与业务代码,实现同步运行
完整代码示例
import cv2 import threading import ctypes import numpy as np # 获取屏幕分辨率 user32 = ctypes.windll.user32 screen_width = user32.GetSystemMetrics(0) screen_height = user32.GetSystemMetrics(1) def play_video_fullscreen(video_path): cap = cv2.VideoCapture(video_path) if not cap.isOpened(): print("无法打开视频文件") return # 获取视频基础参数 video_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) video_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = cap.get(cv2.CAP_PROP_FPS) delay = int(1000 / fps) if fps > 0 else 30 # 计算适配屏幕的尺寸(保持原比例,避免裁剪) scale = min(screen_width / video_width, screen_height / video_height) display_width = int(video_width * scale) display_height = int(video_height * scale) # 创建全屏窗口 cv2.namedWindow("Video", cv2.WND_PROP_FULLSCREEN) cv2.setWindowProperty("Video", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) while cap.isOpened(): ret, frame = cap.read() if not ret: break # 调整画面尺寸并居中填充黑边 frame_resized = cv2.resize(frame, (display_width, display_height)) top_pad = (screen_height - display_height) // 2 left_pad = (screen_width - display_width) // 2 full_frame = np.zeros((screen_height, screen_width, 3), dtype=np.uint8) full_frame[top_pad:top_pad+display_height, left_pad:left_pad+display_width] = frame_resized cv2.imshow("Video", full_frame) # 精准控制帧率,避免卡顿 if cv2.waitKey(delay) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() # 启动视频播放线程(守护线程,主程序结束自动退出) video_thread = threading.Thread(target=play_video_fullscreen, args=("你的视频路径.mp4",)) video_thread.daemon = True video_thread.start() # 主线程同步执行业务代码 while True: print("hi")
关键优化点
- 无裁剪全屏:通过比例计算+黑边填充,保持视频原画面比例,避免边缘裁切
- 流畅播放:根据视频实际帧率设置
waitKey延迟,精准控制播放速度 - 同步执行:多线程分离播放逻辑与业务代码,两者互不阻塞
替代方案(pygame)
若cv2仍有卡顿,pygame对Windows视频播放兼容性更好,同样用多线程实现:
import pygame import threading import time def play_video_pygame(video_path): pygame.init() screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN) screen_width, screen_height = screen.get_size() video = pygame.movie.Movie(video_path) video_width, video_height = video.get_size() # 计算适配比例 scale = min(screen_width/video_width, screen_height/video_height) display_size = (int(video_width*scale), int(video_height*scale)) # 设置视频显示位置(居中) video.set_display(screen, ((screen_width-display_size[0])//2, (screen_height-display_size[1])//2, display_size[0], display_size[1])) video.play() while video.get_busy(): for event in pygame.event.get(): if event.type == pygame.KEYDOWN and event.key == pygame.K_q: video.stop() pygame.quit() return time.sleep(0.01) pygame.quit() # 启动播放线程 video_thread = threading.Thread(target=play_video_pygame, args=("你的视频路径.mp4",)) video_thread.daemon = True video_thread.start() # 主线程同步执行代码 while True: print("hi")
内容的提问来源于stack exchange,提问作者mrithul e
相关产品推荐
相关产品推荐

