前文我们已经完成了一个集暂停、倍速、显示进度条功能为一体的视频播放器,今天我们再来增加一个新的功能——发送弹幕。

tkinter播放视频的原理,就是读取每一帧的图片,然后刷新画布。所以如果想实现弹幕功能,只要获取输入文本框中的文本,再写到图片上就好了。cv2.putText能够实现这个功能,但无法添加中文,所以我们需要换一种方法。

首先,我们需要from PIL import ImageDraw,ImageFont

然后用ImageDraw.Draw转换图片格式,转换后就可以调用.text()往图片上写中文了。

具体实现过程,只需要修改前文的一个函数:

def tkImage(n):

global nowt,pointx,txt

#倍速在这里实现

for i in range(n):

ref,frame = vc1.read()

pilImage = Image.fromarray(frame)

draw = ImageDraw.Draw(pilImage)

font = ImageFont.truetype("simhei.ttf", 40, encoding="utf-8") #参数1:字体文件路径,参数2:字体大小

#txt是读取的Entry内容,在button关联的函数中获取

if txt!="":

draw.text((pointx, pointy), txt, (255, 255, 255), font=font) #pointx, pointy是文字添加的位置

pointx-=10 #每次向左移动10个单位

if(pointx==0):

pointx=size[1]

txt=""

pilImage = cv2.cvtColor(np.array(pilImage), cv2.COLOR_BGR2RGB)

pilImage = Image.fromarray(pilImage)

pilImage = pilImage.resize((window_width, window_height),Image.ANTIALIAS)

tkImage = ImageTk.PhotoImage(image=pilImage)

nowt+=n #记录当前的帧数

return tkImage

现在我们把前文的显示四张图像改成一张,重新整理一下代码:

import time

import tkinter as tk

from tkinter import *

from tkinter import ttk

import cv2

from PIL import Image, ImageTk,ImageFilter,ImageDraw,ImageFont

import multiprocessing

import numpy as np

import random

import os

filePath = 'D:\\movie\\' #电影存放路径

mlist=os.listdir(filePath) #文件夹下所有文件名称

window_width=960 #界面宽

window_height=760 #界面长

image_width=int(window_width*0.5) #图像宽

image_height=int(window_height*0.5) #图像长

imagepos_x=0 #画布位置x

imagepos_y=0 #画布位置Y

lock=0 #暂停标志

n=1 #初始倍速

nowt=0 #当前帧数

nows=0 #当前播放时长(秒)

pointx=0 #弹幕起始点横坐标

pointy=0 #弹幕起始点纵坐标

txt="" #弹幕内容

#获取当前图像

def tkImage(n):

#倍速在这里实现

global nowt,pointx,pointy,txt

for i in range(n):

ref,frame = vc1.read()

pilImage = Image.fromarray(frame)

draw = ImageDraw.Draw(pilImage)

font = ImageFont.truetype("simhei.ttf", 40, encoding="utf-8")#参数1:字体文件路径,参数2:字体大小

if txt!="":

draw.text((pointx, pointy), txt, (255, 255, 255), font=font)

pointx-=10

if(pointx==-50):

pointx=size[1]

txt=""

pilImage = cv2.cvtColor(np.array(pilImage), cv2.COLOR_BGR2RGB)

pilImage = Image.fromarray(pilImage)

pilImage = pilImage.resize((window_width, 720),Image.ANTIALIAS)

tkImage1 = ImageTk.PhotoImage(image=pilImage)

nowt+=n

return tkImage1

#图像的显示与更新

def video():

global nows,nowt

def video_loop():

global nows,nowt

try:

while True:

if lock % 2 == 0: #是否暂停

picture1=tkImage(n)

if nowt >= fps:

nowt=0 #每过一秒则清零重计

nows+=1 #每过一秒,当前播放时间也加1

mi=str(int(nows/60)) #分钟

se=str(int(nows%60)) #秒

if int(mi)<10:

mi="0"+mi

if int(se)<10:

se="0"+se

showt=mi+":"+se #当前时间

show=showt+"/"+totalt #最终显示格式(当前时间/总时长)

tlabel.config(text=show)

canvas.coords(fill_line, (0, 0, int(window_width/tt*nows), 15)) #填充进度条

canvas1.create_image(0,0,anchor='nw',image=picture1)

win.update_idletasks()

win.update()

else:

win.update_idletasks()

win.update()

except:

return

#每次开始播放前初始化

nows,nowt=0,0

canvas.coords(fill_line, (0, 0, 0, 15))

video_loop()

vc1.release()

cv2.destroyAllWindows()

#右键事件:倍速

def right(self):

global n

n+=1

if n>4:

n=1

#左键事件:暂停

def left(self):

global lock

lock+=1

#按钮事件:获取弹幕

def get_txt():

global txt,pointx,pointy

txt=E1.get()

pointx=size[1] #初始x坐标

pointy=random.randint(50,150) #初始y坐标随机

E1.delete(0, END)

#播放选中文件

def start():

global vc1,size,frames_num,fps,totalt,tt,pointx

val = theLB.get() #获得下拉框当前内容

vc1 = cv2.VideoCapture(filePath+val) #读取视频

size = (int(vc1.get(cv2.CAP_PROP_FRAME_HEIGHT)), int(vc1.get(cv2.CAP_PROP_FRAME_WIDTH))) #视频图像的长和宽

frames_num=vc1.get(cv2.CAP_PROP_FRAME_COUNT) #总帧数

fps = vc1.get(cv2.CAP_PROP_FPS) #帧率

totalt=str(int(frames_num/fps/60))+":"+str(int(frames_num/fps)%60) #视频时长

tt=int(frames_num/fps) #进度条叠满所需次数

pointx=size[1] #弹幕起始坐标x

video()

#跳转到指定位置

def kj():

global nows,vc1

time=int(int(s1.get())*frames_num/fps/100) #要跳转到的时长

vc1.set(cv2.CAP_PROP_POS_FRAMES,int(time*fps)) #读取到指定帧数

ref,frame = vc1.read()

nows=time

'''布局'''

win = tk.Tk()

win.geometry(str(window_width+120)+'x'+str(window_height+20))

#显示视频的画布

canvas1 =Canvas(win,bg='white',width=window_width,height=720)

canvas1.place(x=imagepos_x,y=imagepos_y)

canvas1.bind('', left)

canvas1.bind('', right)

#显示进度条的画布

canvas = Canvas(win, width=image_width*2, height=15, bg="white")

canvas.place(x=0, y=722)

fill_line=canvas.create_rectangle(0,0,0,15,fill = 'LightGreen') #坐标是相对于画布的

#弹幕输入框

E1 = Entry(win, bd =5,width=100)

E1.place(x=0, y=745)

#发送弹幕按钮

B1 = Button(win, text="发送", command=get_txt,font=('黑体', 10),fg='blue',width=10,height=2)

B1.place(x=750, y=742)

#显示时间的Label

tlabel = Label(win,font=('黑体', 13),text='')

tlabel.place(x=850, y=750)

#选择影片下拉框

theLB = ttk.Combobox(win,width=12,height=10)

theLB["values"] = mlist

theLB.current(0) #默认选第一个

theLB.place(x=965, y=0)

#播放影片按钮

B2 = Button(win, text="播放", command=start,font=('黑体', 10),fg='red',width=10,height=2)

B2.place(x=980, y=50)

#跳转按钮

B3 = Button(win, text="跳转", command=kj,font=('黑体', 10),fg='red',width=10,height=2)

B3.place(x=980, y=150)

#选择跳转位置的滚动条

s1 = Scale(win,from_=0,to=99,orient=HORIZONTAL) #orient=HORIZONTAL设置水平方向显示

s1.place(x=970, y=100)

win.mainloop()

上述代码不仅实现了我们所说的功能,我还用下拉框Combobox自动加载文件夹下的所有文件名,以供选择文件播放;并且能够拖动滚动条跳转到指定位置,利用了cv2.VideoCapture的.set()方法。

怎么样,更像一个视频播放器了吧?如果你还想往下做,可以加入“添加到播放列表”的功能,选择其他路径下的文件添加到全局变量mlist里,然后更新一下Combobox的values即可。

来看看我们的成果吧:https://www.zhihu.com/video/1240349393213698048

费了半天劲,反正还是只能看默剧。。

python在tk界面播放本地视频_tkinter做一个本地视频播放器(2)——弹幕相关推荐

  1. python在tk界面播放本地视频_如何使用python3在tkinter窗口中插入视频播放器?

    我想用python构建一个视频播放器,但是我的应用程序将有更多的按钮,而不仅仅是play/pause,所以我需要在窗口中插入视频.在 到现在为止我有这个代码:import tkinter import ...

  2. Unity 使用VideoPlayer做一个类似于视频播放器的界面

    Video Player主控脚本 using UnityEngine; using UnityEngine.UI; using UnityEngine.Video;public class Video ...

  3. PC电脑 屏幕竖直截长屏、本地视频转码、本地视频转gif动画、gif压缩等

    PC电脑 屏幕竖直截长屏.本地视频转码.本地视频转gif动画.gif压缩等 写博客贵在坚持.为了让自己和一同进步的人,能够快速理解,并看懂自己的博客. 需要自己对博客编撰尽量完善,要配图.配代码.配动 ...

  4. android 播放视频链接,如何通过Android视频播放器中的直接链接播放MP4视频?

    我正在制作一个 Android应用程序,我需要通过直接下载链接在Android默认本机视频播放器中播放mp4视频. 要打开Android视频播放器,我使用以下代码 Intent intent = ne ...

  5. python播放本地视频_python opencv 读取本地视频文件 修改ffmpeg的方法

    Python + opencv 读取视频的三种情况: 情况一:通过摄像头采集视频 情况二:通过本地视频文件获取视频 情况三:通过摄像头录制视频,再读取录制的视频 摄像头采集.本地视频文件的读取.写视频 ...

  6. 轻松玩转Python:打开文件夹,搜索视频文件,实现简单视频播放器

    目录 1.功能描述: 2.具体实现: 3.代码实现: 4.执行效果: 1.功能描述: 这段代码实现了一个简单的视频播放器,可以打开指定的文件夹并搜索其中的视频文件,将搜索结果展示在列表框中,用户可以选 ...

  7. h5ai界面修改_H5ai修改版,带HTML5视频播放器DPlayer,并支持hls切片播放

    简介 该源码由LOC的冻猫修改,将H5ai的视频播放器替换成了DPlayer.快进什么的方便些,也可以调播放速度.想加弹幕之类的可以自己改代码,3757行里面研究吧. 更新 [2019.6.14] 1 ...

  8. 如何使用Python创建一个自定义视频播放器

    目录 1.安装vlc的64位版本. 2.安装python的vlc模块. 3.编写如下代码,包含了播放,暂停,停止.音量控制功能. 4.来看一看运行结果. 5.如果遇到播放不了的问题,解决方式如下: 这 ...

  9. 卧槽!我用Python做一个打字测试器!看看谁是最快的男人!

    对于平时经常使用电脑的小伙伴而言,一个必不可少的操作就是利用键盘进行打字的操作,想必大家对自己的打字速度也是非常的自信,但是具体的速度大家却不能够准确表述. 今天,小编就同大家利用python制作一款 ...

最新文章

  1. 【SRIO】5、Xilinx RapidIO核例子工程源码分析
  2. Leetcode 844. 比较含退格的字符串 解题思路及C++实现
  3. php中MySQL数据库导入与导出_Mysql数据库导出和导入
  4. Flask项目--发送短信验证码
  5. 技术交底软件_【干货分享】软件类产品如何进行专利挖掘与技术交底书撰写?...
  6. Python next 函数 - Python零基础入门教程
  7. rhel5 给grub 加密,亲测!
  8. 1.11 UML 类图(多看多用就熟悉了)(节选自:《大话设计模式》)
  9. shell读取用户输入
  10. Android-VR 支持流媒体
  11. 人型自走输入法(网页日语输入法)
  12. 思科CCNP认证和华为 HCIP认证网络工程师必须了解的NETCONF四个层面的基本框架
  13. 编辑修改PDF文件的简单方法
  14. 木木早教机器人说明书_机器人操作说明VS小孩使用指南
  15. 两台电脑如何共享文件?如何互相传输文件?
  16. numpy创建伪单位矩阵
  17. 雅思大作文写作--Cities
  18. 美国虚拟主机空间是什么以及具有哪些特点?
  19. DEI1016BD429使用遇到的问题及解决
  20. [234] 回文链表

热门文章

  1. Django解决css样式失效问题最终方法
  2. 20个专业H5(HTML5)动画工具推荐
  3. [量化-029]陈光明投资哲学整理
  4. vue 仿B站下拉刷新上拉加载
  5. Gauss 消元法矩阵LU分解
  6. C中二级指针与它指向的一级指针之间的秘密(深入++*pptr)
  7. Firefox配置阿里云DNS方法
  8. 多少人败给了一个字:等……
  9. 计算机毕业设计Java阿博图书馆管理系统(源码+系统+mysql数据库+lw文档)
  10. liferay mysql driver_Liferay安装笔记(默认安装使用Mysql数据库)