当前位置: 首页 > news >正文

Python实现视频播放器

Python实现视频播放器

Python实现视频播放器,在如下博文中介绍过

Python实现本地视频/音频播放器https://blog.csdn.net/cnds123/article/details/137874107

Python简单GUI程序示例 中 “四、视频播放器” https://blog.csdn.net/cnds123/article/details/122903311

现在再补充介绍一个。读者可以学习比较之。

预备知识

tkinter 是 Python 的标准库之一,用于创建图形用户界面(GUI)。它不需要单独安装,因为它是 Python 安装时自带的模块。

ttk 是 tkinter 的扩展模块,提供了更现代的 GUI 控件(如样式化的按钮、下拉菜单等)。

Style 是 ttk 模块的一部分,用于自定义 GUI 控件的样式。

time 是 Python 的标准库,用于处理时间相关的操作。

threading 是 Python 的标准库,用于实现多线程编程。

需要安装第三方库:opencv-python、pillow、ffpyplayer

cv2 是 OpenCV(Open Source Computer Vision Library)的 Python 接口,用于计算机视觉任务,如图像处理、视频处理等。

pip install opencv-python

Pillow 是 Python Imaging Library(PIL)的一个分支,用于处理图像。

pip install pillow

ffpyplayer 是一个基于 FFmpeg 的 Python 库,用于播放音频和视频。

pip install ffpyplayer

本文介绍了Python实现视频播放器及其改进版本

先看第一个效果图:

源码如下:

import cv2
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk, ImageSequence
from tkinter import ttk
from ffpyplayer.player import MediaPlayer
import time
import threading
from tkinter.ttk import Styleclass VideoPlayTk:def __init__(self):self.__win = tk.Tk()self.__canvas = None     # 画布变量self.__videoWH = [1920, 1080]  # 窗口大小self.__num1 = 0.6# 窗口缩小系数,默认为0.6,最大最好1self.__data = list()self.__uploadImgSize = [150, 150]  # 一个加载视频的gif图片尺寸self.__canvasWH = []     # 画布的宽度 和 高度self.__canvasImg = None  # 画布图片self.__canvasXY = []     # 图片插入到canvas的具体左上角坐标x,yself.__progressBar = None  # 进度条self.__Llabel = None   # 左边显示时间的标签self.__Rlabel = None   # 右边显示时间的标签self.__player = None   # 音频播放 变量self.__scale = None   # 调节音量的控件self.__stopBtn = None   # 暂停按钮self.__stopState = ''  # 一个控制相关线程的变量self.__running = True  # 控制线程运行的标志def sectionOne(self):width = int(self.__videoWH[0] * self.__num1)height = int(self.__videoWH[1] * self.__num1)self.__canvasWH = [width, height]self.__win.title('视频播放器')self.__win.geometry(f'{width}x{height + 90}')self.__win.resizable(height=0, width=0)# 窗口不可放大# 菜单self.__win.iconbitmap('./example.ico')mainMenu = tk.Menu(self.__win)fileMenu = tk.Menu(mainMenu, tearoff=False)# 不添加分割线fileMenu.add_command(label='打开', command=self.__openDir)fileMenu.add_separator()# 设置分割线fileMenu.add_command(label='退出', command=self.__on_close)mainMenu.add_cascade(label='文件', menu=fileMenu)# 在主目录菜单上新增“文件”选项,并通过menu参数与下拉菜单绑定self.__win.config(menu=mainMenu)# 将主菜单设置在窗口上# 画布self.__canvas = tk.Canvas(self.__win, bg='black', width=width, height=height)self.__canvas.grid(row=0, column=0, columnspan=3)self.__Llabel = tk.Label(self.__win, text='00:00:00', font=('华文宋体', 12))self.__Llabel.grid(row=1, column=0)# 进度条style = Style()style.theme_use('clam')style.configure("my0.Horizontal.TProgressbar", troughcolor='white', background='red')# 设置进度条的颜色progressBar = ttk.Progressbar(self.__win, orient=tk.HORIZONTAL,style='my0.Horizontal.TProgressbar')progressBar.grid(row=1, column=1)progressBar['length'] = width - 200progressBar['value'] = 0self.__progressBar = progressBarself.__Rlabel = tk.Label(self.__win, text='00:00:00', font=('华文宋体', 12))self.__Rlabel.grid(row=1, column=2)self.__stopBtn = tk.Button(self.__win,text='暂停',font=('华文宋体', 12),command=self.__fun5)self.__stopBtn.grid(row=2,column=0,sticky=tk.E)# 音量self.__scale = tk.Scale(self.__win, from_=0, to=100, resolution=1, length=120, orient=tk.HORIZONTAL,font=('华文宋体', 12),command=self.__fun2)self.__scale.grid(row=2, column=1, sticky=tk.E)self.__scale.set(100)self.__win.protocol("WM_DELETE_WINDOW", self.__on_close)self.__win.mainloop()def __on_close(self):self.__running = False  # 停止线程if self.__player is not None:self.__player.close_player()self.__win.quit()self.__win.destroy()  # 确保窗口被销毁# 暂停播放的方法def __fun5(self):if self.__player is not None:self.__player.set_pause(True)# 点击暂停按钮,视频播放暂停self.__stopState = 'stop'# 设置暂停播放状态# 调节音量的方法def __fun2(self, value):if self.__player is not None:self.__player.set_volume(int(value) / 100)# value 值的范围为0~100,set_volume方法参数取值为0.0 ~ 1.0# 将总的时间(单位秒)进行相关格式化  如 119 为 00:01:59def __getTime(self,totleTime):hour = 0minute = totleTime//60if minute > 60:hour = minute // 60second = int(totleTime%60)return '{:02d}:{:02d}:{:02d}'.format(hour,minute,second)def __openDir(self):fileName = filedialog.askopenfilename()# 视频文件的绝对路径if fileName != '':cap = cv2.VideoCapture(filename=fileName)self.__data = list()w = cap.get(propId=cv2.CAP_PROP_FRAME_WIDTH)h = cap.get(propId=cv2.CAP_PROP_FRAME_HEIGHT)fps = cap.get(propId=cv2.CAP_PROP_FPS)count = cap.get(propId=cv2.CAP_PROP_FRAME_COUNT)print('时长:',int(count*(1/fps)))self.__data = [int(w), int(h), int(fps), int(count),int(count*(1/fps))]print(self.__data)# 使用cv2获取视频的尺寸,比如1920*1080,帧率(1秒以内变换图片的张数),图片的总数,总时长canvas_x = 0canvas_y = 0if w / self.__canvasWH[0] == h / self.__canvasWH[1]:print('图片大小1920*1080')bi = w / self.__canvasWH[0]else:if w / self.__canvasWH[0] > h / self.__canvasWH[1]:bi = w / self.__canvasWH[0]canvas_y = int((self.__canvasWH[1] - h / bi) // 2)else:bi = h / self.__canvasWH[1]canvas_x = int((self.__canvasWH[0] - w / bi) // 2)self.__canvasXY = [canvas_x, canvas_y]# 根据视频的尺度用于确定画布 图片左上角坐标# 下面这一段代码可以注释,只是实现播放视频时实现视频加载图标w = self.__canvasWH[0]h = self.__canvasWH[1]x = (w - self.__uploadImgSize[0]) // 2y = (h - self.__uploadImgSize[1]) // 2self.__canvas.delete(tk.ALL)img_i = 0while img_i < 5:uploadImg = Image.open('upload.gif')iter = ImageSequence.Iterator(uploadImg)for frame in iter:pic = ImageTk.PhotoImage(frame)self.__canvas.create_image(x, y, image=pic, anchor=tk.W)time.sleep(0.01)self.__canvas.update()img_i += 1size = (int(self.__data[0] / bi), int(self.__data[1] / bi))self.__player = MediaPlayer(filename=fileName)thread1 = threading.Thread(target=self.__fun3)# 时间加载的线程thread2 = threading.Thread(target=self.__fun4)# 时间进度条的线程thread1.start()thread2.start()print('执行主程序!')self.__fun1(size)self.__player.close_player()cap.release()# 时间进度条def __fun4(self):progressBar = self.__progressBarprogressBar['maximum'] = self.__data[4]progressBar['value'] = 0for i in range(self.__data[4]+1):if not self.__running:breakif self.__stopState == 'stop':breakprogressBar['value'] += 1time.sleep(1)# 时间展示def __fun3(self):print(self.__getTime(self.__data[4]))self.__Rlabel['text'] = self.__getTime(self.__data[4])second1 = 0minute1 = 0hour1 = 0for i in range(self.__data[4]+1):if not self.__running:breakif second1 != 0 and second1 == 60:minute1 += 1second1 = 0if minute1 == 59 and second1 == 60:hour1 += 1minute1 = 0second1 = 0if self.__stopState == 'stop':breakself.__Llabel['text'] = '{:02d}:{:02d}:{:02d}'.format(hour1,minute1,second1)time.sleep(1)second1 += 1# 播放图片def __fun1(self, size):i = 0self.__canvas.delete(tk.ALL)self.__stopState = ''while i < self.__data[3]:if not self.__running:breakframe, val = self.__player.get_frame()if self.__stopState == 'stop':breakif val == 'eof':self.__player.set_pause(True) # 需要!不信你试试breakelif frame is None:if i != 0:self.__player.set_pause(True)# self.__player.close_player()breakelse:time.sleep(0.01)else:image, pts = framebytes_1 = bytes(image.to_bytearray()[0])img2 = Image.frombytes("RGB", image.get_size(), bytes_1)img2 = img2.resize(size=size,resample=Image.ANTIALIAS)self.__canvasImg = ImageTk.PhotoImage(image=img2)self.__canvas.create_image(self.__canvasXY[0], self.__canvasXY[1], image=self.__canvasImg, anchor=tk.NW)self.__canvas.update()time.sleep(1/self.__data[2])i += 1if __name__ == '__main__':a = VideoPlayTk()a.sectionOne()

改进,添加“继续”播放按钮

先看效果图:

源码如下:

import cv2
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk, ImageSequence
from tkinter import ttk
from ffpyplayer.player import MediaPlayer
import time
import threading
from tkinter.ttk import Styleclass VideoPlayTk:def __init__(self):self.__win = tk.Tk()self.__canvas = None     # 画布变量self.__videoWH = [1920, 1080]  # 窗口大小self.__num1 = 0.6# 窗口缩小系数,默认为0.6,最大最好1self.__data = list()self.__uploadImgSize = [150, 150]  # 一个加载视频的gif图片尺寸self.__canvasWH = []     # 画布的宽度 和 高度self.__canvasImg = None  # 画布图片self.__canvasXY = []     # 图片插入到canvas的具体左上角坐标x,yself.__progressBar = None  # 进度条self.__Llabel = None   # 左边显示时间的标签self.__Rlabel = None   # 右边显示时间的标签self.__player = None   # 音频播放 变量self.__scale = None   # 调节音量的控件self.__stopBtn = None   # 暂停按钮self.__resumeBtn = None  # 继续按钮self.__stopState = ''  # 一个控制相关线程的变量self.__running = True  # 控制线程运行的标志self.__current_frame = 0  # 当前播放的帧数self.__video_thread = None  # 视频播放线程self.__progress_thread = None  # 进度条更新线程self.__progress_value = 0  # 保存进度条的当前值self.__time_value = 0  # 保存时间标签的当前值self.__video_finished = False  # 视频播放结束标志def sectionOne(self):width = int(self.__videoWH[0] * self.__num1)height = int(self.__videoWH[1] * self.__num1)self.__canvasWH = [width, height]self.__win.title('视频播放器')self.__win.geometry(f'{width}x{height + 120}')  # 增加高度以容纳更多按钮self.__win.resizable(height=0, width=0)# 窗口不可放大# 菜单self.__win.iconbitmap('./example.ico')mainMenu = tk.Menu(self.__win)fileMenu = tk.Menu(mainMenu, tearoff=False)# 不添加分割线fileMenu.add_command(label='打开', command=self.__openDir)fileMenu.add_separator()# 设置分割线fileMenu.add_command(label='退出', command=self.__on_close)mainMenu.add_cascade(label='文件', menu=fileMenu)# 在主目录菜单上新增“文件”选项,并通过menu参数与下拉菜单绑定self.__win.config(menu=mainMenu)  # 将主菜单设置在窗口上# 画布self.__canvas = tk.Canvas(self.__win, bg='black', width=width, height=height)self.__canvas.grid(row=0, column=0, columnspan=3)self.__Llabel = tk.Label(self.__win, text='00:00:00', font=('华文宋体', 12))self.__Llabel.grid(row=1, column=0)# 进度条style = Style()style.theme_use('clam')style.configure("my0.Horizontal.TProgressbar", troughcolor='white', background='red')# 设置进度条的颜色progressBar = ttk.Progressbar(self.__win, orient=tk.HORIZONTAL, style='my0.Horizontal.TProgressbar')progressBar.grid(row=1, column=1)progressBar['length'] = width - 200progressBar['value'] = 0self.__progressBar = progressBarself.__Rlabel = tk.Label(self.__win, text='00:00:00', font=('华文宋体', 12))self.__Rlabel.grid(row=1, column=2)# 暂停按钮self.__stopBtn = tk.Button(self.__win, text='暂停', font=('华文宋体', 12), command=self.__pause_video)self.__stopBtn.grid(row=2, column=0, sticky=tk.E)# 继续按钮self.__resumeBtn = tk.Button(self.__win, text='继续', font=('华文宋体', 12), command=self.__resume_video)self.__resumeBtn.grid(row=2, column=1)  # , sticky=tk.E# 音量self.__scale = tk.Scale(self.__win, from_=0, to=100, resolution=1, length=120, orient=tk.HORIZONTAL,font=('华文宋体', 12), command=self.__adjust_volume)self.__scale.grid(row=2, column=2) # , sticky=tk.Eself.__scale.set(100)self.__win.protocol("WM_DELETE_WINDOW", self.__on_close)self.__win.mainloop()def __on_close(self):self.__running = False  # 停止线程if self.__player is not None:self.__player.close_player()self.__win.quit()self.__win.destroy()  # 确保窗口被销毁# 暂停视频def __pause_video(self):if self.__player is not None:self.__player.set_pause(True)self.__stopState = 'stop'  # 设置暂停状态self.__progress_value = self.__progressBar['value']  # 保存进度条的当前值self.__time_value = self.__get_seconds_from_time(self.__Llabel['text'])  # 保存时间标签的当前值# 继续视频def __resume_video(self):if self.__player is not None:self.__player.set_pause(False)self.__stopState = ''  # 清除暂停状态# 如果视频播放线程已经结束,重新启动它if self.__video_thread is None or not self.__video_thread.is_alive():size = (int(self.__data[0] / (self.__data[0] / self.__canvasWH[0])), int(self.__data[1] / (self.__data[1] / self.__canvasWH[1])))self.__video_thread = threading.Thread(target=self.__play_video, args=(size,))self.__video_thread.start()# 如果进度条线程已经结束,重新启动它if self.__progress_thread is None or not self.__progress_thread.is_alive():self.__progress_thread = threading.Thread(target=self.__update_progress)self.__progress_thread.start()# 如果时间标签线程已经结束,重新启动它if not hasattr(self, '__time_thread') or not self.__time_thread.is_alive():self.__time_thread = threading.Thread(target=self.__update_time)self.__time_thread.start()# 调节音量的方法def __adjust_volume(self, value):if self.__player is not None:self.__player.set_volume(int(value) / 100)# value 值的范围为0~100,set_volume方法参数取值为0.0 ~ 1.0# 将总的时间(单位秒)进行相关格式化  如 119 为 00:01:59def __getTime(self, totleTime):hour = 0minute = totleTime // 60if minute > 60:hour = minute // 60second = int(totleTime % 60)return '{:02d}:{:02d}:{:02d}'.format(hour, minute, second)# 将时间字符串转换为秒数def __get_seconds_from_time(self, time_str):h, m, s = map(int, time_str.split(':'))return h * 3600 + m * 60 + sdef __openDir(self):fileName = filedialog.askopenfilename()# 视频文件的绝对路径if fileName != '':# 停止当前视频播放self.__running = Falseif self.__player is not None:self.__player.close_player()if self.__video_thread is not None and self.__video_thread.is_alive():self.__video_thread.join()if self.__progress_thread is not None and self.__progress_thread.is_alive():self.__progress_thread.join()if hasattr(self, '__time_thread') and self.__time_thread.is_alive():self.__time_thread.join()# 重置状态变量self.__running = Trueself.__stopState = ''self.__progress_value = 0self.__time_value = 0self.__video_finished = False# 重置时间轴和进度条self.__Llabel['text'] = '00:00:00'self.__Rlabel['text'] = '00:00:00'self.__progressBar['value'] = 0cap = cv2.VideoCapture(filename=fileName)self.__data = list()w = cap.get(propId=cv2.CAP_PROP_FRAME_WIDTH)h = cap.get(propId=cv2.CAP_PROP_FRAME_HEIGHT)fps = cap.get(propId=cv2.CAP_PROP_FPS)count = cap.get(propId=cv2.CAP_PROP_FRAME_COUNT)print('时长:', int(count * (1 / fps)))self.__data = [int(w), int(h), int(fps), int(count), int(count * (1 / fps))]print(self.__data)# 使用cv2获取视频的尺寸,比如1920*1080,帧率(1秒以内变换图片的张数),图片的总数,总时长canvas_x = 0canvas_y = 0if w / self.__canvasWH[0] == h / self.__canvasWH[1]:print('图片大小1920*1080')bi = w / self.__canvasWH[0]else:if w / self.__canvasWH[0] > h / self.__canvasWH[1]:bi = w / self.__canvasWH[0]canvas_y = int((self.__canvasWH[1] - h / bi) // 2)else:bi = h / self.__canvasWH[1]canvas_x = int((self.__canvasWH[0] - w / bi) // 2)self.__canvasXY = [canvas_x, canvas_y]# 根据视频的尺度用于确定画布 图片左上角坐标# 下面这一段代码可以注释,只是实现播放视频时实现视频加载图标w = self.__canvasWH[0]h = self.__canvasWH[1]x = (w - self.__uploadImgSize[0]) // 2y = (h - self.__uploadImgSize[1]) // 2self.__canvas.delete(tk.ALL)img_i = 0while img_i < 5:uploadImg = Image.open('upload.gif')iter = ImageSequence.Iterator(uploadImg)for frame in iter:pic = ImageTk.PhotoImage(frame)self.__canvas.create_image(x, y, image=pic, anchor=tk.W)time.sleep(0.01)self.__canvas.update()img_i += 1size = (int(self.__data[0] / bi), int(self.__data[1] / bi))self.__player = MediaPlayer(filename=fileName)self.__video_thread = threading.Thread(target=self.__play_video, args=(size,))self.__video_thread.start()self.__progress_thread = threading.Thread(target=self.__update_progress)self.__progress_thread.start()self.__time_thread = threading.Thread(target=self.__update_time)self.__time_thread.start()print('执行主程序!')cap.release()# 时间进度条def __update_progress(self):progressBar = self.__progressBarprogressBar['maximum'] = self.__data[4]progressBar['value'] = self.__progress_value  # 从保存的位置恢复进度条for i in range(self.__progress_value, self.__data[4] + 1):if not self.__running or self.__video_finished:breakif self.__stopState == 'stop':breakprogressBar['value'] = itime.sleep(1)# 时间展示def __update_time(self):self.__Rlabel['text'] = self.__getTime(self.__data[4])second1 = self.__time_value % 60minute1 = (self.__time_value // 60) % 60hour1 = self.__time_value // 3600for i in range(self.__time_value, self.__data[4] + 1):if not self.__running or self.__video_finished:breakif second1 != 0 and second1 == 60:minute1 += 1second1 = 0if minute1 == 59 and second1 == 60:hour1 += 1minute1 = 0second1 = 0if self.__stopState == 'stop':breakself.__Llabel['text'] = '{:02d}:{:02d}:{:02d}'.format(hour1, minute1, second1)time.sleep(1)second1 += 1self.__time_value += 1# 播放视频def __play_video(self, size):i = 0self.__canvas.delete(tk.ALL)self.__stopState = ''while i < self.__data[3]:if not self.__running:breakframe, val = self.__player.get_frame()if self.__stopState == 'stop':breakif val == 'eof':self.__video_finished = True  # 设置视频播放结束标志self.__player.set_pause(True) # 需要!不信你试试breakelif frame is None:if i != 0:self.__player.set_pause(True)breakelse:time.sleep(0.01)else:image, pts = framebytes_1 = bytes(image.to_bytearray()[0])img2 = Image.frombytes("RGB", image.get_size(), bytes_1)img2 = img2.resize(size=size, resample=Image.ANTIALIAS)self.__canvasImg = ImageTk.PhotoImage(image=img2)self.__canvas.create_image(self.__canvasXY[0], self.__canvasXY[1], image=self.__canvasImg, anchor=tk.NW)self.__canvas.update()time.sleep(1 / self.__data[2])i += 1if __name__ == '__main__':a = VideoPlayTk()a.sectionOne()

OK!

相关文章:

Python实现视频播放器

Python实现视频播放器 Python实现视频播放器&#xff0c;在如下博文中介绍过 Python实现本地视频/音频播放器https://blog.csdn.net/cnds123/article/details/137874107 Python简单GUI程序示例 中 “四、视频播放器” https://blog.csdn.net/cnds123/article/details/122903…...

介绍一款飞算JavaAI编程工具,集成到idea,图文并茂

飞算的插件下载地址&#xff0c;里边也有安装步骤&#xff1a; JavaAI 下载 从file-》setting-》plugin&#xff0c;然后走图中所示 选择从磁盘安装插件&#xff1a;找到下载好的压缩包然后进行idea重启 根据提示模块可以生成代码&#xff0c;就是需要等待&#xff0c;后期不…...

【大数据】Spark Executor内存分配原理与调优

【大数据】Spark Executor内存管理与调优 Executor内存总体布局 统一内存管理 堆内内存 (On-heap Memory) 堆外内存 (Off-heap Memory) Execution 内存和 Storage 内存动态占用机制 任务内存管理&#xff08;Task Memory Manager&#xff09; 只用了堆内内存的示例 用了…...

Python 课堂点名桌面小程序

一、场景分析 闲来无事&#xff0c;老婆说叫我开发一个课堂点名桌面小程序&#xff0c;给她在课堂随机点名学生问问题。 人生苦短&#xff0c;那就用 Python 给她写一个吧。 二、依赖安装 因为要用到 excel&#xff0c;所以安装两个依赖&#xff1a; pip install openpyxl…...

配置Spring Boot中的Jackson序列化

配置Spring Boot中的Jackson序列化 在开发基于Spring Boot的应用程序时&#xff0c;Jackson是默认的JSON序列化和反序列化工具。它提供了强大的功能&#xff0c;可以灵活地处理JSON数据。然而&#xff0c;Jackson的默认行为可能无法完全满足我们的需求。例如&#xff0c;日期格…...

Rust学习总结之-match

Rust 有一个叫做 match 的极为强大的控制流运算符&#xff0c;它允许我们将一个值与一系列的模式相比较&#xff0c;并根据相匹配的模式执行相应代码。模式可由字面量、变量、通配符和许多其他内容构成。 一&#xff1a;match定义 可以把 match 表达式想象成某种硬币分类器&a…...

实践教程:使用DeepSeek实现PDF转Word的高效方案

&#x1f388;Deepseek推荐工具 PDF文件因其跨平台、格式稳定的特性被广泛使用&#xff0c;但在内容编辑场景中&#xff0c;用户常需将PDF转换为可编辑的Word文档。传统的付费工具&#xff08;如Adobe Acrobat&#xff09;或在线转换平台存在成本高、隐私风险等问题。本文将使…...

鸿蒙 ArkUI 实现 2048 小游戏

2048 是一款经典的益智游戏&#xff0c;玩家通过滑动屏幕合并相同数字的方块&#xff0c;最终目标是合成数字 2048。本文基于鸿蒙 ArkUI 框架&#xff0c;详细解析其实现过程&#xff0c;帮助开发者理解如何利用声明式 UI 和状态管理构建此类游戏。 一、核心数据结构与状态管理…...

az devops login报错:Failed to authenticate using the supplied token.

PowerShell&#xff0c;az devops login报错&#xff1a; Failed to authenticate using the supplied token. 检查了一下PAT token是对的。 检查命令&#xff1a; az devops login --organization https://dev.azure.com/xxxxxxxx/ 乍一看好像没问题问题&#xff0c;然后想…...

C ++ 静态存储区+堆空间

静态存储区 特点&#xff1a; 1&#xff1a;生命周期很长&#xff0c;main函数开始之前就存在&#xff0c;main函数结束&#xff0c;才结束 2&#xff1a;同名变量的管理&#xff0c;与栈不一样(重名变量前提&#xff0c;作用域一样)&#xff1a; 栈&#xff1a;遇到重名变…...

gtest 和 gmock讲解

Google Test&#xff08;gtest&#xff09;和 Google Mock&#xff08;gmock&#xff09;是 Google 开发的用于 C 的测试框架和模拟框架&#xff0c;以下是对它们的详细讲解&#xff1a; Google Test&#xff08;gtest&#xff09; 简介 Google Test 是一个用于 C 的单元测试框…...

docker的下载与使用(一)

本文默认使用linux系统以及会linux的基本指令&#xff0c;windows下安装docker较为繁琐 docker是什么 Docker 是一个开源的应用容器引擎&#xff0c;基于go 语言并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&…...

鸿蒙HarmonyOS NEXT开发:组件-样式-基础 2

// 1 // 2 ArkUI 基本语法 // 方舟开发框架(简称:ArkUI),是一套 构建HarmonyOS应用 界面 的框架。 // 构建页面的最小单位就是 "组件"。 // 组件名(参数) { // 内容 // } // .属性1() // .属性2() // .属性N() import text from @ohos.graphics.text // @En…...

如何理解数据库的几种事务隔离级别?以及如何理解脏读、不可重复度、幻读?

在多用户并发访问数据库时&#xff0c;数据库系统需要通过事务隔离级别来控制不同事务之间的相互影响。不同的隔离级别可以避免或减少在并发环境下可能出现的数据不一致或冲突。常见的事务隔离级别有四种&#xff1a;读未提交&#xff08;Read Uncommitted&#xff09;、读已提…...

计算机网络基础简答题资料(对口高考)

1、什么是计算机网络&#xff1f;计算机网络的功能有哪些&#xff1f; 答案&#xff1a;计算机网络&#xff0c;是指将分布在不同地理位置、具有独立功能的多台计算机及其外围设备&#xff0c;通过通信设备和通信线路连接起来&#xff0c;在网络操作系统、网络管理软件及网络通…...

在docker容器中运行vllm部署deepseek-r1大模型

# 在本地部署python环境 cd /app/ python -m venv myenv # 激活虚拟环境 source /app/myenv/activate # 要撤销激活一个虚拟环境&#xff0c;请输入: deactivate# 进入虚拟环境安装modelscope pip install modelscope# 下载大模型&#xff08;7B为例&#xff09; modelscope do…...

HeidiSQL如何替换代码中的某些信息

1.SQL代码里的某些内容&#xff0c;比如2025年这个日期信息&#xff0c;我想替换成2024年的&#xff0c;按照:“搜索”---“替换文本”然后按照图片上的步骤来就可以了&#xff0c;特别是在sql代码有几百行甚至几千行的时候使用 2.SQL代码的表格对象中的数据如何一次性把某个内…...

Wireshark 插件开发实战指南

Wireshark 插件开发实战指南 环境搭建流程图 #mermaid-svg-XpNibno7BIyfzNn5 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XpNibno7BIyfzNn5 .error-icon{fill:#552222;}#mermaid-svg-XpNibno7BIyfzNn5 .error-t…...

【大模型➕知识图谱】大模型结合医疗知识图谱:解锁智能辅助诊疗系统新范式

【大模型➕知识图谱】大模型结合医疗知识图谱:解锁智能辅助诊疗系统新范式 大模型结合医疗知识图谱:解锁智能辅助诊疗系统新范式引言一、系统架构1.1 系统架构图1.2 架构模块说明1.2.1 用户输入1.2.2 大模型(语义理解与意图识别)1.2.3 Agent(问题解析与任务分配)1.2.4 问…...

大模型应用落地具体规划方案

摘要 本篇文章主要探讨大模型应用落地的具体规划方案&#xff0c;包含六点内容的分享&#xff0c;分别是&#xff1a; 大模型本地部署架构 大模型应用交互场景 基于阿里云RAG 项目的实现方案 大模型推荐落地场景方案 大模型应用落地发展规划 大模型开源架构选型推荐 在阅…...

【Qt】MVC设计模式

目录 一、搭建MVC框架 二、创建数据库连接单例类SingleDB 三、数据库业务操作类model设计 四、control层&#xff0c;关于model管理类设计 五、view层即为窗口UI类 一、搭建MVC框架 里面的bin、lib、database文件夹以及sqlite3.h与工程后缀为.pro文件的配置与上次发的文章…...

python量化交易——金融数据管理最佳实践——qteasy创建本地数据源

文章目录 qteasy金融历史数据管理总体介绍本地数据源——DataSource对象默认数据源查看数据表查看数据源的整体信息最重要的数据表其他的数据表 从数据表中获取数据向数据表中添加数据删除数据表 —— 请尽量小心&#xff0c;删除后无法恢复&#xff01;&#xff01;总结 qteas…...

深入探索Python机器学习算法:监督学习(线性回归,逻辑回归,决策树与随机森林,支持向量机,K近邻算法)

文章目录 深入探索Python机器学习算法&#xff1a;监督学习一、线性回归二、逻辑回归三、决策树与随机森林四、支持向量机五、K近邻算法 深入探索Python机器学习算法&#xff1a;监督学习 在机器学习领域&#xff0c;Python凭借其丰富的库和简洁的语法成为了众多数据科学家和机…...

word转换为pdf后图片失真解决办法、高质量PDF转换方法

1、安装Adobe Acrobat Pro DC 自行安装 2、配置Acrobat PDFMaker &#xff08;1&#xff09;点击word选项卡上的Acrobat插件&#xff0c;&#xff08;2&#xff09;点击“首选项”按钮&#xff0c;&#xff08;3&#xff09;点击“高级配置”按钮&#xff08;4&#xff09;点…...

【MATLAB例程】三维下的IMM(交互式多模型),模型使用CV(匀速)和CA(匀加速)

给出三维下的交互式多模型&#xff08;IMM&#xff09;matlab例程&#xff0c;模型使用匀速运动CV和匀加速运动CA&#xff0c;滤波使用EKF&#xff08;扩展卡尔曼滤波&#xff09; 文章目录 代码运行结果程序结构 代码讲解模型定义&#xff1a;轨迹生成&#xff1a;IMM核心流程…...

千峰React:Hooks(下)

useLayoutEffect useLayoutEffect在useEffect之前触发 这样会闪屏&#xff0c;因为是异步的&#xff0c;两次都渲染了 import {useEffect,useState } from react;function App() {const [msg,setMsg] useState(hello App)useEffect(() > {setMsg(hello useEffect)});retu…...

突破网络壁垒:实现 Mac SSH 访问 Windows WSL Ubuntu 的最佳实践20250301

突破网络壁垒&#xff1a;实现 Mac SSH 访问 Windows WSL Ubuntu 的最佳实践 背景与痛点 在现代开发环境中&#xff0c;开发者通常会面临不同操作系统之间的协同工作。例如&#xff1a; 主要开发环境位于 Windows 的 WSL Ubuntu 子系统需要从局域网内的 Mac 设备进行远程访问…...

【开源-鸿蒙土拨鼠大理石系统】鸿蒙 HarmonyOS Next App+微信小程序+云平台

✨本人自己开发的开源项目&#xff1a;土拨鼠充电系统 ✨踩坑不易&#xff0c;还希望各位大佬支持一下&#xff0c;在GitHub给我点个 Start ⭐⭐&#x1f44d;&#x1f44d; ✍GitHub开源项目地址&#x1f449;&#xff1a;https://github.com/lusson-luo/HarmonyOS-groundhog-…...

RAG 阿里云

RAG-阿里云Spring AI Alibaba官网官网 RAG-阿里云Spring AI Alibaba官网官网 AI应用跑起来&#xff0c;取消一下航班的操作666...

python -ssh学习

def exe_sshcmd(ip,username,userpswd,port,cmd): """ 功能&#xff1a;SSH登录到指定设备&#xff0c;并执行对应的命令 入参&#xff1a;前四项为ssh登录shell的ip和port&#xff0c;具备管理员权限的用户名和密码&#xff0c; cmd可以…...

【Java学习】内部类

面向对象系列六 一、类级别 1.静态成员 2.非静态成员与方法 二、类的创建与成员管理 1.类的创建 2.类的成员管理 三、常见的内部类 1.非静态内部类 2.静态内部类 3.匿名内部类 4.局部内部类 一、类级别 1.1静态成员 静态成员是类级别的是能一路直属都是在类层面的&…...

养生,开启健康生活之门

在这个快节奏的时代&#xff0c;人们在忙碌奔波中&#xff0c;往往忽略了自身健康。养生保健&#xff0c;不再是老年人的专属&#xff0c;而是各个年龄段维持良好生活状态的关键&#xff0c;它是我们开启健康生活的一把钥匙。 规律作息是养生的基石。人体就像一台精密的仪器&am…...

1-3压缩命令

文章目录 1. tar1.1 压缩&#xff08;.tar.gz .tgz .tar.bz2 &#xff09;1.2 解压缩(.tar.gz .tgz .tar.bz2 ) 2.zip2.1 压缩(.zip)2.2 解压缩 3.xz3.1 压缩&#xff08;.tar.xz&#xff09;3.2 解压缩 1. tar 1.1 压缩&#xff08;.tar.gz .tgz .tar.bz2 &#xff09; c…...

Dify使用和入门

第一步&#xff1a;了解 Dify 在开始之前&#xff0c;先简单了解一下 Dify 是什么&#xff1a; Dify 是一个开源的 LLM 应用开发平台&#xff0c;专注于帮助开发者快速构建生产级的生成式 AI 应用。它支持知识库集成、RAG&#xff08;检索增强生成&#xff09;技术、复杂工作…...

AcWing 5933:爬楼梯 ← 递归 / 递推 / 高精度

【题目来源】 https://www.acwing.com/problem/content/5936/ 【题目描述】 树老师爬楼梯&#xff0c;他可以每次走 1 级或者 2 级&#xff0c;输入楼梯的级数&#xff0c;求不同的走法数。 例如&#xff1a;楼梯一共有 3 级&#xff0c;他可以每次都走一级&#xff0c;或者第…...

WebGL 渲染器 WebGLRenderer

目录 Three.js封装的渲染器 .domElement属性 .setSize(width, height)方法 帧缓冲区的相关封装 渲染器方法.clear(color,depth,stencil) 渲染器方法.clearDepth() 渲染器属性.autoClear Three.js封装的渲染器 .domElement属性 如果想通过WebGL渲染一个三维场景&#…...

基于Three.js的3D赛车游戏开发实战详解

目录 一、项目效果预览二、核心技术架构2.1 三维场景构建2.2 赛道与车辆模型2.3 光照系统三、核心运动系统3.1 车辆运动控制3.2 物理模拟公式3.3 边界限制四、摄像机控制系统4.1 第三人称视角数学原理4.2 鼠标交互实现五、星空背景特效5.1 点云生成算法5.2 动态闪烁效果六、性能…...

⭐算法OJ⭐位操作实战【计数】(C++ 实现)

191. Number of 1 Bits Given a positive integer n, write a function that returns the number of set bits in its binary representation (also known as the Hamming weight). int hammingWeight(uint32_t n) {int count 0;while (n) {count n & 1; // 检查最低位…...

【通俗讲解电子电路】——从零开始理解生活中的科技(一)

导言&#xff1a;电子电路为什么重要&#xff1f; ——看不见的“魔法”&#xff0c;如何驱动你的生活&#xff1f; 清晨&#xff0c;当你的手机闹钟响起时&#xff0c;你可能不会想到&#xff0c;是电子电路在精准控制着时间的跳动&#xff1b;当你用微波炉加热早餐时&#…...

浏览器JS打不上断点,一点就跳到其他文件里。浏览器控制台 js打断点,指定的位置打不上断点,一打就跳到其他地方了。

关闭JavaScript 源代码映射&#xff0c;F12开发者模式 设置->偏好设置->源代码/来源->JavaScript 源代码映射。 肯定不是这个原因导致的&#xff0c;但这个办法可以暂时解决问题&#xff0c;点完这个东西就隐藏了webpack&#xff0c;有懂的来讲讲。 又浪费一个小时…...

浅谈人工智能之Windows安装llama factory

浅谈人工智能之Windows安装llama factory Llama Factory 是一个强大的工具&#xff0c;旨在帮助用户轻松管理和优化Llama模型的训练和部署。在某些情况下&#xff0c;您可能需要在部分互联网连接的环境中安装和使用Llama Factory。本文将详细介绍如何在Windows系统上这种情况下…...

mac电脑中使用无线诊断.app查看连接的Wi-Fi带宽

问题 需要检查连接到的Wi-Fi的AP硬件支持的带宽。 步骤 1.按住 Option 键&#xff0c;然后点击屏幕顶部的Wi-Fi图标&#xff1b;2.从下拉菜单中选择 “打开无线诊断”&#xff08;Open Wireless Diagnostics&#xff09;&#xff1b;3.你可能会看到一个提示窗口&#xff0c;…...

Python--内置模块和开发规范(下)

2. 开发规范 2.1 单文件应用 文件结构示例 # 文件注释 import os import jsonDB_PATH "data.json" # 常量放顶部def load_data():"""函数注释&#xff1a;加载数据"""if os.path.exists(DB_PATH):with open(DB_PATH, "r"…...

vue3配置端口,比底部vue调试

import { fileURLToPath, URL } from ‘node:url’ import { defineConfig } from ‘vite’ import vue from ‘vitejs/plugin-vue’ import vueJsx from ‘vitejs/plugin-vue-jsx’ // 关闭vue底部调试模式 // import vueDevTools from ‘vite-plugin-vue-devtools’ // htt…...

代码随想录day51

647. /** lc appleetcode.cn id647 langcpp** [647] 回文子串*/// lc codestart #include<iostream> #include<vector> #include<string> using namespace std; class Solution { public:int countSubstrings(string s) {vector<vector<bool>> …...

B2B2C多语言电商系统代销逻辑设计和开发

随着全球电商市场的快速发展&#xff0c;B2B2C&#xff08;Business-to-Business-to-Consumer&#xff09;模式逐渐成为企业拓展业务的重要方式。特别是在多语言、多文化的国际市场环境中&#xff0c;B2B2C多语言电商系统的代销功能为企业提供了灵活的业务模式&#xff0c;帮助…...

示波器探头衰减值:简单来说就是“信号缩小器

一、什么是衰减值 衰减值就是探头把信号“缩小”多少倍再传给示波器。比如&#xff1a; 1X衰减&#xff1a;信号原样传输&#xff08;不缩小&#xff09;&#xff0c;适合测小电压&#xff08;比如手机电池3.7V&#xff09;。 10X衰减&#xff1a;信号缩小10倍&#xff0c;适…...

Nginx系列06(Nginx 缓存配置、SSL/TLS 配置)

目录 Nginx 缓存配置 SSL/TLS 配置 Nginx 缓存配置 概念&#xff1a;Nginx 缓存配置允许服务器将频繁访问的资源&#xff08;如网页、图片、脚本等&#xff09;存储在内存或磁盘中&#xff0c;当再次接收到相同请求时&#xff0c;直接从缓存中读取并返回&#xff0c;减少对后…...

JavaScript——前端基础3

目录 JavaScript简介 优点 可做的事情 运行 第一个JavaScript程序 搭建开发环境 安装的软件 操作 在浏览器中使用JavaScript文件 分离JS 使用node运行JS文件 语法 变量与常量 原生数据类型 模板字符串 字符串的内置方法 数组 对象 对象数组和JSON if条件语…...

操作系统知识点12

1.在操作系统的结构设计中&#xff0c;采用层次结构的操作系统其最大优点是把整体问题局部化 2.非特权指令是指操作系统和用户均可以使用的指令 3.向处理器发出的中断信号称为中断请求 4.轮转法RR是单纯基于时间片考虑的 5.当进程处于就绪状态时&#xff0c;表示进程已获得…...