使用python实现视频播放器(支持拖动播放位置跳转)

使用python实现视频播放器(支持拖动播放位置跳转)

Python实现视频播放器,在我早期的博文中介绍或作为资料记录过

Python实现视频播放器 https://blog.csdn.net/cnds123/article/details/145926189

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

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

但是,一直不尽人意。现在,再介绍一个。

这是一个基于 PyQt6 和 python-vlc 开发的视频播放器,主要实现了我多次试图实现未果的功能

——带有播放进度条,不仅显示播放进度,还支持拖动播放位置跳转。

普通版视频播放器

主要特点

    播放画面随窗口缩放

    支持常见格式(MP4、AVI、MKV 等)

    通过文件对话框加载视频文件

    播放/暂停、停止、播放进度跳转、音量调节

    显示视频文件名、当前播放时间、总时长

播放进度条:显示播放进度并支持拖动播放位置跳转。

音量滑块:音量滑块调整音量大小。

需安装以下 Python第三方库:

python-vlc、 PyQt6

Windows中,还要安装 VLC 播放器,其下载 地址 https://www.videolan.org/vlc/ 。否则,将报错:缺少 libvlc.dll。

运行效果界面如下:

基本使用操作

    打开文件:点击菜单栏 文件 > 打开文件(快捷键 Ctrl+O) 或底部 打开文件 按钮

    播放/暂停:空格键 或 点击 按钮切换

    停止:停止 按钮   

    进度跳转:拖动进度条

    音量调节:拖动底部音量滑块

源码如下:

import sys
import time
import vlc
import os
from PyQt6 import QtWidgets, QtCore, QtGuiclass VLCPlayer(QtWidgets.QMainWindow):def __init__(self):super().__init__()self.instance = vlc.Instance()self.player = self.instance.media_player_new()self.timer = QtCore.QTimer(self)self.timer.timeout.connect(self.update_ui)self.current_file = Noneself.media_loaded = Falseself.init_ui()def init_ui(self):# 主窗口设置self.setWindowTitle("PyQt6 VLC Player")self.resize(800, 600)# 创建菜单栏menubar = self.menuBar()file_menu = menubar.addMenu("文件(&F)")# 添加"打开"动作open_action = QtGui.QAction("打开文件...", self)open_action.setShortcut("Ctrl+O")open_action.triggered.connect(self.open_file)file_menu.addAction(open_action)# 创建主容器和布局central_widget = QtWidgets.QWidget(self)self.setCentralWidget(central_widget)main_layout = QtWidgets.QVBoxLayout(central_widget)main_layout.setContentsMargins(0, 0, 0, 0)# 视频标题标签 self.title_label = QtWidgets.QLabel("当前未选择媒体文件")self.title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)self.title_label.setStyleSheet("font-size: 14px; color: #666; margin: 5px;")main_layout.addWidget(self.title_label)# 视频显示区域self.video_widget = QtWidgets.QWidget()self.video_widget.setStyleSheet("background-color: black;")main_layout.addWidget(self.video_widget, stretch=1)# 控制面板control_panel = QtWidgets.QWidget()control_layout = QtWidgets.QVBoxLayout(control_panel)# 进度条self.progress_bar = QtWidgets.QSlider(QtCore.Qt.Orientation.Horizontal)self.progress_bar.setMinimum(0)self.progress_bar.sliderMoved.connect(self.set_position)control_layout.addWidget(self.progress_bar)# 时间标签self.time_label = QtWidgets.QLabel("00:00:00 / 00:00:00")control_layout.addWidget(self.time_label)# 控制按钮button_layout = QtWidgets.QHBoxLayout()self.play_btn = QtWidgets.QPushButton("播放")self.play_btn.clicked.connect(self.toggle_play)self.stop_btn = QtWidgets.QPushButton("停止")self.stop_btn.clicked.connect(self.stop)self.open_btn = QtWidgets.QPushButton("打开文件")self.open_btn.clicked.connect(self.open_file)# 音量控制self.volume_slider = QtWidgets.QSlider(QtCore.Qt.Orientation.Horizontal)self.volume_slider.setRange(0, 100)self.volume_slider.setValue(100)self.volume_slider.valueChanged.connect(self.set_volume)# 添加控件button_layout.addWidget(self.open_btn)button_layout.addWidget(self.play_btn)button_layout.addWidget(self.stop_btn)button_layout.addWidget(QtWidgets.QLabel("音量:"))button_layout.addWidget(self.volume_slider)control_layout.addLayout(button_layout)main_layout.addWidget(control_panel)# 设置VLC渲染if sys.platform == "win32":self.player.set_hwnd(int(self.video_widget.winId()))elif sys.platform == "linux":self.player.set_xwindow(self.video_widget.winId())elif sys.platform == "darwin":from PyQt6.QtGui import QCocoaNativeContextself.player.set_nsobject(int(QCocoaNativeContext(self.video_widget.winId()).nsview()))self.timer.start(200)def open_file(self):# 修复1:打开文件前先停止播放if self.player.is_playing():self.player.stop()self.media_loaded = Falseself.play_btn.setText("播放")file_dialog = QtWidgets.QFileDialog(self)file_dialog.setNameFilter("视频文件 (*.mp4 *.avi *.mkv *.mov *.flv)")if file_dialog.exec():selected_files = file_dialog.selectedFiles()if selected_files:self.load_media(selected_files[0])def load_media(self, file_path):try:# 新增:停止定时器避免冲突self.timer.stop()# 修复2:确保彻底释放旧媒体资源self.player.stop()self.player.set_media(None)  # 清除旧媒体引用# 重置状态self.media_loaded = Falseself.play_btn.setText("播放")self.progress_bar.setValue(0)self.time_label.setText("00:00:00 / 00:00:00")# 加载新文件self.current_file = file_pathmedia = self.instance.media_new(file_path)self.player.set_media(media)# 更新标题file_name = os.path.basename(file_path)self.title_label.setText(f"当前播放: {file_name}")# 修复3:异步解析媒体信息(避免阻塞UI)media.parse_with_options(vlc.MediaParseFlag.network, 1000)# 设置进度条最大值self.progress_bar.setMaximum(media.get_duration())self.media_loaded = True# 显示总时长total_time = time.strftime("%H:%M:%S", time.gmtime(media.get_duration() // 1000))self.time_label.setText(f"00:00:00 / {total_time}")# 新增:确保媒体加载完成后再启定时器self.timer.start(200)except Exception as e:QtWidgets.QMessageBox.critical(self, "错误", f"无法加载文件:\n{str(e)}")self.media_loaded = Falseself.title_label.setText("媒体加载失败")def toggle_play(self):if not self.media_loaded:self.open_file()return# 修复4:强制同步按钮状态if self.player.is_playing():self.player.pause()self.play_btn.setText("播放")else:self.player.play()self.play_btn.setText("暂停")def stop(self):self.player.stop()self.progress_bar.setValue(0)self.time_label.setText("00:00:00 / 00:00:00")self.play_btn.setText("播放")self.title_label.setText("播放已停止")def set_volume(self, value):self.player.audio_set_volume(value)def set_position(self, value):if self.player.is_seekable():self.player.set_position(value / self.progress_bar.maximum())def update_ui(self):if not self.media_loaded:return  # 新增:防止在无媒体时更新media_length = self.player.get_length()if media_length > 0:current_time = self.player.get_time()# 新增:检测播放结束if current_time >= media_length - 500:  # 留50ms容差self.stop()returnself.progress_bar.setMaximum(media_length)self.progress_bar.setValue(current_time)total_time = time.strftime("%H:%M:%S", time.gmtime(media_length // 1000))current_time_str = time.strftime("%H:%M:%S", time.gmtime(current_time // 1000))self.time_label.setText(f"{current_time_str} / {total_time}")def closeEvent(self, event):self.player.stop()event.accept()if __name__ == "__main__":app = QtWidgets.QApplication(sys.argv)player = VLCPlayer()player.show()sys.exit(app.exec())

专用版视频播放控制器(视频播控器)

主要添加视频“加密”、“解密”功能

运行条件除了和上面的一样外,还需安装第三方库pycryptodome

pycryptodome 是一个强大的加密库,用于实现加密算法。

界面如下:

1)加密视频

菜单栏点击 安全 → 加密视频

优先当前播放文件路径,即:

    如果当前正在播放视频且未加密 → 弹出确认对话框

    否则 → 弹出文件选择对话框

加密文件的后缀 .vef,放在原文将后缀之后。命名规则为:原文件名.vef(如 video.mp4 → video.mp4.vef)

2)解密视频

菜单栏点击 安全 → 解密视频

文件过滤:仅显示 .vef 文件

解密文件,出现保存对话框,默认放置在原位置,默认用文件名(可改),若存放处有同名文件,提示是否替换。

命名规则:自动去除 .vef 后缀 → video.mp4

解密时,若输入的密码和加密时不一致,提示:密码错误或文件损坏 → 立即终止并提示

源码如下:

import sys
import time
import hashlib
import secrets
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import vlc
import os
from PyQt6 import QtWidgets, QtCore, QtGuiclass VLCPlayer(QtWidgets.QMainWindow):def __init__(self):super().__init__()self.instance = vlc.Instance()self.player = self.instance.media_player_new()self.timer = QtCore.QTimer(self)self.timer.timeout.connect(self.update_ui) # 连接定时器到更新方法self.current_file = Noneself.media_loaded = Falseself.temp_files = set() #用于跟踪临时解密文件self.init_ui()self.init_crypto()def init_ui(self):# 主窗口设置self.setWindowTitle("视频播控器(特别专用版)")self.resize(800, 600)# 初始化菜单menubar = self.menuBar()file_menu = menubar.addMenu("文件(&F)")crypto_menu = menubar.addMenu("安全(&S)")# 文件操作open_action = self.create_action("打开文件...", "Ctrl+O", self.open_file)# exit_action = self.create_action("退出", "Ctrl+Q", lambda: self.close()) # 播放退出太慢# 加密解密操作encrypt_action = self.create_action("加密视频...", "Ctrl+E", self.encrypt_video)decrypt_action = self.create_action("解密视频...", "Ctrl+D", self.decrypt_video)# 添加菜单项file_menu.addAction(open_action)file_menu.addSeparator()# file_menu.addAction(exit_action)crypto_menu.addAction(encrypt_action)crypto_menu.addAction(decrypt_action)# 创建主容器和布局central_widget = QtWidgets.QWidget(self)self.setCentralWidget(central_widget)main_layout = QtWidgets.QVBoxLayout(central_widget)main_layout.setContentsMargins(0, 0, 0, 0)# 视频标题标签 self.title_label = QtWidgets.QLabel("当前未选择媒体文件")self.title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)self.title_label.setStyleSheet("font-size: 14px; color: #666; margin: 5px;")main_layout.addWidget(self.title_label)# 视频显示区域self.video_widget = QtWidgets.QWidget()self.video_widget.setStyleSheet("background-color: black;")main_layout.addWidget(self.video_widget, stretch=1)# 控制面板control_panel = QtWidgets.QWidget()control_layout = QtWidgets.QVBoxLayout(control_panel)# 进度条self.progress_bar = QtWidgets.QSlider(QtCore.Qt.Orientation.Horizontal)self.progress_bar.setMinimum(0)self.progress_bar.sliderMoved.connect(self.set_position)control_layout.addWidget(self.progress_bar)# 时间标签self.time_label = QtWidgets.QLabel("00:00:00 / 00:00:00")control_layout.addWidget(self.time_label)# 控制按钮button_layout = QtWidgets.QHBoxLayout()self.play_btn = QtWidgets.QPushButton("播放")self.play_btn.clicked.connect(self.toggle_play)self.stop_btn = QtWidgets.QPushButton("停止")self.stop_btn.clicked.connect(self.stop)self.open_btn = QtWidgets.QPushButton("打开文件")self.open_btn.clicked.connect(self.open_file)# 音量控制self.volume_slider = QtWidgets.QSlider(QtCore.Qt.Orientation.Horizontal)self.volume_slider.setRange(0, 100)self.volume_slider.setValue(100)self.volume_slider.valueChanged.connect(self.set_volume)# 添加控件button_layout.addWidget(self.open_btn)button_layout.addWidget(self.play_btn)button_layout.addWidget(self.stop_btn)button_layout.addWidget(QtWidgets.QLabel("音量:"))button_layout.addWidget(self.volume_slider)control_layout.addLayout(button_layout)main_layout.addWidget(control_panel)# 设置VLC渲染if sys.platform == "win32":self.player.set_hwnd(int(self.video_widget.winId()))elif sys.platform == "linux":self.player.set_xwindow(self.video_widget.winId())elif sys.platform == "darwin":from PyQt6.QtGui import QCocoaNativeContextself.player.set_nsobject(int(QCocoaNativeContext(self.video_widget.winId()).nsview()))self.timer.start(200)def init_crypto(self):"""初始化加密参数"""self.key_derivation_iterations = 100000self.salt_size = 16self.nonce_size = 16self.tag_size = 16self.chunk_size = 64 * 1024  # 64KB块处理def create_action(self, text, shortcut, callback):"""创建标准化菜单动作"""action = QtGui.QAction(text, self)action.setShortcut(shortcut)action.triggered.connect(callback)return action        def open_file(self):# 修复1:打开文件前先停止播放if self.player.is_playing():self.player.stop()self.media_loaded = Falseself.play_btn.setText("播放")file_dialog = QtWidgets.QFileDialog(self)file_dialog.setNameFilter("视频文件 (*.mp4 *.avi *.mkv *.mov *.flv)")if file_dialog.exec():selected_files = file_dialog.selectedFiles()if selected_files:self.load_media(selected_files[0])def load_media(self, file_path):try:# 如果是加密文件需要特殊处理if file_path.lower().endswith('.vef'):QtWidgets.QMessageBox.warning(self, "警告", "请使用菜单中的解密功能打开加密文件")return# 新增:停止定时器避免冲突self.timer.stop()# 修复2:确保彻底释放旧媒体资源self.player.stop()self.player.set_media(None)  # 清除旧媒体引用# 重置状态self.media_loaded = Falseself.play_btn.setText("播放")self.progress_bar.setValue(0)self.time_label.setText("00:00:00 / 00:00:00")# 加载新文件self.current_file = file_pathmedia = self.instance.media_new(file_path)self.player.set_media(media)# 更新标题file_name = os.path.basename(file_path)self.title_label.setText(f"当前播放: {file_name}")# 修复3:异步解析媒体信息(避免阻塞UI)media.parse_with_options(vlc.MediaParseFlag.network, 1000)# 设置进度条最大值self.progress_bar.setMaximum(media.get_duration())self.media_loaded = True# 显示总时长total_time = time.strftime("%H:%M:%S", time.gmtime(media.get_duration() // 1000))self.time_label.setText(f"00:00:00 / {total_time}")# 新增:确保媒体加载完成后再启定时器self.timer.start(200)except Exception as e:QtWidgets.QMessageBox.critical(self, "错误", f"无法加载文件:\n{str(e)}")self.media_loaded = Falseself.title_label.setText("媒体加载失败")def toggle_play(self):if not self.media_loaded:self.open_file()return# 修复4:强制同步按钮状态if self.player.is_playing():self.player.pause()self.play_btn.setText("播放")else:self.player.play()self.play_btn.setText("暂停")# ---------- 加密解密功能 ----------def _get_encrypted_filename(self, src_path):"""生成加密文件名(原文件名+.vef)"""return src_path + ".vef"  # 直接在原文件名后追加.vefdef encrypt_video(self):"""智能加密方法:优先处理当前播放文件"""# 自动检测当前播放文件src_path = Noneif self.current_file and os.path.exists(self.current_file):# 检查是否已经是加密文件if not self.current_file.lower().endswith('.vef'):reply = QtWidgets.QMessageBox.question(self, '加密确认', f"是否加密当前播放的文件?\n{os.path.basename(self.current_file)}",QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No)if reply == QtWidgets.QMessageBox.StandardButton.Yes:src_path = self.current_file# 如果无当前可用文件,则选择文件if not src_path:src_path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "选择要加密的视频文件", "","视频文件 (*.mp4 *.avi *.mkv *.mov *.flv)")if not src_path:return# 处理加密文件特殊情况if src_path.lower().endswith('.vef'):QtWidgets.QMessageBox.warning(self, "警告", "不能加密已加密文件")return# 获取保存路径default_name = self._get_encrypted_filename(os.path.basename(src_path))dest_path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "保存加密文件", os.path.join(os.path.dirname(src_path), default_name),  # 默认原目录"加密视频 (*.vef)")if not dest_path:return# 获取密码password, ok = QtWidgets.QInputDialog.getText(self, "输入密码", "设置加密密码:", QtWidgets.QLineEdit.EchoMode.Password)if not ok or not password:return# 执行加密流程try:# 如果是当前播放文件,停止播放was_playing = Falseif src_path == self.current_file:was_playing = self.player.is_playing()self.player.stop()self.media_loaded = Falseself._encrypt_file(src_path, dest_path, password)# 成功提示msg = f"加密成功!\n原文件: {os.path.basename(src_path)}\n加密文件: {os.path.basename(dest_path)}"QtWidgets.QMessageBox.information(self, "完成", msg)# 如果加密的是当前文件,询问是否加载加密文件if src_path == self.current_file:choice = QtWidgets.QMessageBox.question(self, "加载文件", "是否立即加载加密后的文件?",QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No)if choice == QtWidgets.QMessageBox.StandardButton.Yes:self.load_media(dest_path)except Exception as e:self.show_error(f"加密失败: {str(e)}")finally:# 恢复原始状态(如果需要)if was_playing and src_path != dest_path:self.load_media(src_path)def _encrypt_file(self, src_path, dest_path, password):"""执行文件加密(新增)"""try:# 生成加密参数salt = secrets.token_bytes(self.salt_size)key = hashlib.pbkdf2_hmac('sha256',password.encode('utf-8'),salt,self.key_derivation_iterations,dklen=32)cipher = AES.new(key, AES.MODE_GCM)cipher.update(salt)# 分块加密with open(src_path, 'rb') as fin, open(dest_path, 'wb') as fout:# 写入加密头fout.write(salt)fout.write(cipher.nonce)while True:chunk = fin.read(self.chunk_size)if not chunk:breakencrypted = cipher.encrypt(pad(chunk, AES.block_size))fout.write(encrypted)# 写入认证标签fout.write(cipher.digest())except PermissionError:raise RuntimeError("文件被其他程序占用,请关闭后重试")except Exception as e:raise RuntimeError(f"加密失败: {str(e)}")def _get_decrypted_filename(self, src_path):"""生成解密文件名(去除.vef后缀)"""if src_path.lower().endswith('.vef'):return src_path[:-4]  # 去除.vefreturn src_path + "_decrypted"def decrypt_video(self):"""增强型解密方法"""try:# 选择加密文件src_file, _ = QtWidgets.QFileDialog.getOpenFileName(self, "选择要解密的文件", "", "加密视频 (*.vef)")if not src_file:return# 生成默认保存路径default_path = self._get_decrypted_filename(src_file)dest_file, _ = QtWidgets.QFileDialog.getSaveFileName(self, "保存解密文件",default_path,  # 默认原目录+去后缀"视频文件 (*.*)")if not dest_file:return# 检查文件是否已存在if os.path.exists(dest_file):reply = QtWidgets.QMessageBox.question(self, "文件存在",f"目标文件已存在,是否覆盖?\n{dest_file}",QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No)if reply != QtWidgets.QMessageBox.StandardButton.Yes:return# 获取密码password, ok = QtWidgets.QInputDialog.getText(self, "输入密码", "解密密码:", QtWidgets.QLineEdit.EchoMode.Password)if not ok or not password:return# 执行解密decrypted_path = self._decrypt_file(src_file, password, dest_file)if decrypted_path:QtWidgets.QMessageBox.information(self, "成功", f"文件解密成功!\n保存路径: {decrypted_path}")self.load_media(decrypted_path)except Exception as e:self.show_error(f"解密失败: {str(e)}")def _decrypt_file(self, src_path, password, dest_path):"""增强型解密方法(保存到指定路径)"""try:with open(src_path, 'rb') as fin:salt = fin.read(self.salt_size)nonce = fin.read(self.nonce_size)key = self._derive_key(password, salt)cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)cipher.update(salt)with open(dest_path, 'wb') as fout:encrypted = fin.read()ciphertext, tag = encrypted[:-self.tag_size], encrypted[-self.tag_size:]# 分块解密写入chunk_size = self.chunk_size + AES.block_sizefor i in range(0, len(ciphertext), chunk_size):chunk = ciphertext[i:i+chunk_size]decrypted = unpad(cipher.decrypt(chunk), AES.block_size)fout.write(decrypted)# 验证标签cipher.verify(tag)return dest_pathexcept ValueError as ve:# 清理已写入的部分文件if os.path.exists(dest_path):try:os.remove(dest_path)except:passraise ValueError("解密失败 - 密码错误或文件损坏") from veexcept Exception as e:if os.path.exists(dest_path):try:os.remove(dest_path)except:passraise RuntimeError(f"解密过程错误: {str(e)}") from edef _derive_key(self, password, salt):"""生成加密密钥"""return hashlib.pbkdf2_hmac('sha256',password.encode('utf-8'),salt,self.key_derivation_iterations,dklen=32  # AES-256需要32字节密钥)# ---------- 辅助功能 ----------def show_error(self, message):"""显示错误提示"""QtWidgets.QMessageBox.critical(self, "错误", message)def closeEvent(self, event):"""关闭处理,清理临时文件"""for temp_file in self.temp_files:try:if os.path.exists(temp_file):os.remove(temp_file)except Exception as e:print(f"删除临时文件失败: {str(e)}")self.player.stop() # 停止播放器event.accept()  # def stop(self):self.player.stop()self.progress_bar.setValue(0)self.time_label.setText("00:00:00 / 00:00:00")self.play_btn.setText("播放")self.title_label.setText("播放已停止")def set_volume(self, value):self.player.audio_set_volume(value)def set_position(self, value):if self.player.is_seekable():self.player.set_position(value / self.progress_bar.maximum())def update_ui(self):if not self.media_loaded:return  # 新增:防止在无媒体时更新media_length = self.player.get_length()if media_length > 0:current_time = self.player.get_time()# 新增:检测播放结束if current_time >= media_length - 500:  # 留50ms容差self.stop()returnself.progress_bar.setMaximum(media_length)self.progress_bar.setValue(current_time)total_time = time.strftime("%H:%M:%S", time.gmtime(media_length // 1000))current_time_str = time.strftime("%H:%M:%S", time.gmtime(current_time // 1000))self.time_label.setText(f"{current_time_str} / {total_time}")if __name__ == "__main__":app = QtWidgets.QApplication(sys.argv)player = VLCPlayer()player.show()sys.exit(app.exec())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/76585.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用Python和Pygame创造粉色粒子爱心:3D渲染的艺术

引言 在计算机图形学中,3D效果的2D渲染是一个迷人的领域。今天,我将分享一个使用Python和Pygame库创建的粉色粒子爱心效果。这个项目不仅视觉效果惊艳,而且代码简洁易懂,非常适合图形编程初学者学习3D渲染的基础概念。 项目概述…

在汇编层面理解MESI

理解MESI协议在汇编层面的表现需要结合缓存一致性机制和处理器指令执行的行为。以下是分步骤的解释: 1. MESI协议基础 MESI是缓存行(Cache Line)状态的协议,定义四种状态: Modified(修改)&…

爱瑞编程2025暑期CSP集训营开始招生啦!

一、什么是暑期CSP集训营? 为全力备战2025年9月CSP-J/S认证,举办的线下编程集训活动。 旨在通过高强度编程训练,帮助学员提升竞赛能力,冲刺一等奖。 二、为什么参加集训营? 高效编程特训:封闭式学习&…

问题大集10-git使用commit提交中文显示乱码

(1)问题 (2)解决步骤 1) 设置全局编码为 UTF-8 git config --global core.quotepath false git config --global i18n.commitEncoding utf-8 git config --global i18n.logOutputEncoding utf-8 2) 显示或设…

当AI开始“思考“:大语言模型的文字认知三部曲

引言:从《黑客帝国》说起 1999年上映的科幻经典《黑客帝国》描绘了一个令人震撼的未来图景——人类生活在一个由人工智能构造的数字矩阵中。当我们观察现代大型语言模型的工作原理时,竟发现与这个虚构世界有着惊人的相似:人们正在用矩阵以及矩…

Golang改进后的任务调度系统分析

以下是整合了所有改进点的完整代码实现: package mainimport ("bytes""context""fmt""io""log""net/http""sync""time""github.com/go-redis/redis/v8""github.com/robfig/…

前沿技术有哪些改变生活新趋势

太阳能技术正在改变的生活 它让移动设备有了新的能源选择 太阳能板能直接把阳光转成电能 这对户外活动或者电力不便的地方特别有用 比如现在市面上有不少太阳能充电宝 小巧便携 可以随时给手机平板充电 需要注意的是 这些设备得放在太阳下才能工作 但它们确实能让人在野外多用…

基于飞桨框架3.0本地DeepSeek-R1蒸馏版部署实战

深度学习框架与大模型技术的融合正推动人工智能应用的新一轮变革。百度飞桨(PaddlePaddle)作为国内首个自主研发、开源开放的深度学习平台,近期推出的3.0版本针对大模型时代的开发痛点进行了系统性革新。其核心创新包括“动静统一自动并行”&…

C++设计模式-模板方法模式:从基本介绍,内部原理、应用场景、使用方法,常见问题和解决方案进行深度解析

一、基本介绍 模板方法模式(Template Method Pattern)是行为型设计模式,其核心思想是定义算法骨架,将具体步骤延迟到子类实现。如同烹饪菜谱的标准化流程:所有厨师遵循相同的操作流程(备料→烹饪→装盘&am…

Spring Boot 自定义日志打印(日志级别、logback-spring.xml 文件、自定义日志打印解读)

一、Logback 在 Spring Boot 中,日志框架默认使用的是 Logback,Spring Boot 提供了对日志配置的简化 Spring Boot 默认会将日志输出到控制台,并且日志级别为 INFO 可以在 application.yaml 或 application.properties 文件中进行日志配置 …

Python 异步编程:如何将同步文件操作函数无缝转换为异步版本

在 Python 的异步编程世界中,os.path 模块的同步文件操作函数常常让我们陷入两难境地:直接使用它们会阻塞事件循环,降低程序性能;但这些函数又如此方便实用。今天,我将带你探索如何巧妙地将这些同步函数转换为异步版本,让你的异步程序既能享受高效的事件处理,又能无缝利…

CUDA概览

一、CUDA 是什么? CUDA(Compute Unified Device Architecture,计算统一设备架构)是 NVIDIA 于2006年推出的并行计算平台与编程模型,旨在通过 GPU 的大规模并行计算能力加速科学计算、数据处理、人工智能等领域的计算任…

CSS3学习教程,从入门到精通, 学院网站完整项目 - HTML5 + CSS3 实现(25)

学院网站完整项目 - HTML5 CSS3 实现 下面是一个完整的学院网站项目,包含主页、新闻列表页、新闻详情页和视频宣传页的实现。我将按照您的要求提供详细的代码和注释。 项目结构 college-website/ ├── index.html # 主页 ├── news-list.html …

Ubuntu离线安装mysql

在 Ubuntu 24.04 上离线安装 MySQL 的步骤如下(支持 MySQL 8.0 或 8.4): 一.安装方法 此次安装是按照方法一安装,其它方法供参考: 安装成功截图: 安全配置截图: sudo mysql_secure_installat…

SQL Server 2022 读写分离问题整合

跟着热点整理一下遇到过的SQL Server的问题,这篇来聊聊读写分离遇到的和听说过的问题。 一、读写分离实现方法 1. 原生高可用方案 1.1 Always On 可用性组(推荐方案) 配置步骤: -- 1. 启用Always On功能 USE [master] GO ALT…

【前端扫盲】postman介绍及使用

Postman 是一款专为 API 开发与测试设计的 全流程协作工具,程序员可通过它高效完成接口调试、自动化测试、文档管理等工作。以下是针对程序员的核心功能介绍和应用场景说明: 一、核心功能亮点 接口请求构建与调试 支持所有 HTTP 方法(GET/POS…

IdeaVim-AceJump

‌AceJump 是一款专为IntelliJ IDEA平台打造的开源插件,旨在通过简单的快捷键操作帮助用户快速跳转到编辑器中的任何符号位置,如变量名、方法调用或特定的字符串‌。无论是大型项目还是日常编程,AceJump 都能显著提升你的代码导航速度和效率。…

[C语言入门] 结构体

目录 1. 啥是结构体 2. 啥是结构体变量 3. 创建结构体变量的小细节 3.1 创建全局结构体变量(不推荐) 3.2 创建局部结构体变量(不推荐) 3.3 创建局部结构体变量Plus 4. 结构体在内存里面咋存? 5. 结构体作为参数…

贤小二c#版Yolov5 yolov8 yolov10 yolov11自动标注工具 + 免python环境 GPU一键训练包

贤小二c#版yolo标注训练工具集 欢迎使用贤小二AI标注训练系统v2.0 本课程所有演示程序全部免费 1、这节课程主要演示贤小二AI标注训练系统的使用,以及标注数据时注意事项和技巧; 2、本程序采用c# Net8.0框架开发,是贤小二开发的一款Yolo标注…

二分类交叉熵损失

二分类交叉熵损失(Binary Cross-Entropy Loss)是用于二分类问题的常见损失函数。它衡量的是模型输出的预测概率分布与真实标签之间的差异。 1 二分类问题 在二分类问题中,每个样本的目标输出是 0 或 1,表示样本属于某一类或另一类…