我正在尝试制作互动视频并实际播放视频我已获得此代码: *它是从这里的另一篇文章修改的代码。
def player(canvas):
b = video.get_next_data()
frame_image = ImageTk.PhotoImage(Image.fromarray(b))
canvas.create_image(600, 400.5, image= frame_image)
root.after(0.001, player(canvas))
if __name__ == "__main__":
root = tk.Tk()
root.geometry("1920x1080")
canvas = tk.Canvas(root, width="1920", height="1080")
canvas.pack()
thread = threading.Thread(target=player, args=(canvas,))
thread.daemon = 60
thread.start()
root.mainloop()
我正在使用画布,稍后我需要添加一个按钮,它将覆盖视频。我也使用了一个while循环,它仍然口吃。
视频在播放时断断续续,我看了一眼任务经理,我认为它可能是口吃,因为它使用了太多的内存。无论如何,有人可以帮助解决这个问题吗?任何建议也将非常感激。谢谢!!!
答案 0 :(得分:1)
您可以使用两种不同的方法来处理长时间运行的功能。
首先只使用after()
def player(canvas):
b = video.get_next_data()
frame_image = ImageTk.PhotoImage(Image.fromarray(b))
canvas.create_image(600, 400.5, image= frame_image)
# run it again after 16ms
root.after(16, lambda:player(canvas))
# --- main ---
root = tk.Tk()
root.geometry("1920x1080")
canvas = tk.Canvas(root, width="1920", height="1080")
canvas.pack()
# start player
player(canvas)
root.mainloop()
第二次使用threading
def player(canvas):
while True
b = video.get_next_data()
frame_image = ImageTk.PhotoImage(Image.fromarray(b))
canvas.create_image(600, 400.5, image= frame_image)
time.sleep(0.16)
# --- main ---
root = tk.Tk()
root.geometry("1920x1080")
canvas = tk.Canvas(root, width="1920", height="1080")
canvas.pack()
thread = threading.Thread(target=player, args=(canvas,))
thread.daemon = 60
thread.start()
root.mainloop()
因为tkinter
不是线程安全的,所以第二种方法有时可能不起作用。
其他问题 - 已在上面的代码中解决 - after
期待"回调" - 它表示没有()
和参数的函数名称。要使用需要参数的函数,您必须使用lambda
来创建不带参数的函数。
root.after(16, lambda:player(canvas))
最后一个问题 - 对于你创建新PhotoImage
和新object on canvas (using
create_image`的每个视频帧,所以最后你在画布上有很多对象(一个在另一个上面)和许多内存中的对象。
您必须在PhotoImage
上创建一个Canvas
并替换此对象中的数据。
我无法测试它,但它可能是这样的
def player(canvas_image):
b = video.get_next_data()
frame_image = ImageTk.PhotoImage(Image.fromarray(b))
if canvas_image is None:
# create first canvas image
canvas_image = canvas.create_image(600, 400.5, image=frame_image)
else:
# replace image in canvas object
canvas.itemconfig(canvas_image, image=frame_image)
root.after(16, lambda:player(canvas_image))
# --- main ---
root = tk.Tk()
root.geometry("1920x1080")
canvas = tk.Canvas(root, width="1920", height="1080")
canvas.pack()
canvas_image = None
player(canvas_image)
root.mainloop()
或使用两个变量
def player(frame_image, canvas_image):
b = video.get_next_data()
if canvas_image is None:
# create first canvas image
frame_image = ImageTk.PhotoImage(Image.fromarray(b))
canvas_image = canvas.create_image(600, 400.5, image=frame_image)
else:
# replace image in canvas object
frame_image.paste(Image.fromarray(b))
canvas.itemconfig(canvas_image, image=frame_image)
root.after(16, lambda:player(frame_image, canvas_image))
# --- main ---
root = tk.Tk()
root.geometry("1920x1080")
canvas = tk.Canvas(root, width="1920", height="1080")
canvas.pack()
frame_image = None
canvas_image = None
player(frame_image, canvas_image)
root.mainloop()
带有全局变量的EDIT:版本
def player(): # without `frame_image`, `canvas_image`
global frame_image
global canvas_image
b = video.get_next_data()
if canvas_image is None:
# create first canvas image
frame_image = ImageTk.PhotoImage(Image.fromarray(b))
canvas_image = canvas.create_image(600, 400.5, image=frame_image)
else:
# replace image in canvas object
frame_image.paste(Image.fromarray(b))
canvas.itemconfig(canvas_image, image=frame_image)
root.after(16, player) # without `frame_image`, `canvas_image`
# --- main ---
root = tk.Tk()
root.geometry("1920x1080")
canvas = tk.Canvas(root, width="1920", height="1080")
canvas.pack()
frame_image = None
canvas_image = None
player() # without `frame_image`, `canvas_image`
root.mainloop()