Python Video是口吃的

时间:2018-01-08 10:43:33

标签: python video tkinter

我正在尝试制作互动视频并实际播放视频我已获得此代码: *它是从这里的另一篇文章修改的代码。

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循环,它仍然口吃。

视频在播放时断断续续,我看了一眼任务经理,我认为它可能是口吃,因为它使用了太多的内存。无论如何,有人可以帮助解决这个问题吗?任何建议也将非常感激。谢谢!!!

1 个答案:

答案 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()