PyQt6音乐播放器崩溃
我通过点击“添加到播放列表”来加载播放列表。当我点击列表中的任何一项时,播放器运行得很好。但是如果我尝试点击列表中的另一首曲子,程序就会崩溃。
我注意到了以下几点:
- 如果我点击某首曲子,然后再点击一次,所有功能都正常,我可以从列表中选择其他曲子而不会崩溃。
- 如果我点击某首曲子,然后用滑块或按钮快进音乐,我也可以选择列表中的其他曲子而不会崩溃。
- 但是如果我点击某首曲子,然后直接点击另一首,而没有先快进之前选择的曲子,程序就会崩溃。
- 我还注意到每次选择新曲子时都会出现这种错误:[mp3float @ 000001A17DE3A040] 无法更新跳过样本的时间戳。
我尝试修复这个问题,但没有成功。谢谢你的帮助。
import os
import sys
from PyQt6.QtCore import Qt, QUrl, QTimer
from PyQt6.QtMultimedia import QMediaPlayer, QAudioOutput, QAudio
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QSlider, QVBoxLayout, QHBoxLayout, QLabel, QFileDialog, \
QListWidget, QListWidgetItem
class MusicPlayer(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Music Player")
self.setGeometry(100, 100, 400, 200)
self.initUI()
self.initPlayer()
self.initSlider()
self.initTimer()
def initTimer(self):
self.tmr0 = QTimer()
self.tmr0.timeout.connect(self.on_time)
# self.tmr0.setInterval(5000)
self.tmr0.start(1)
def on_time(self):
if not self.position_slider.isSliderDown():
pos = self.player.position()
self.position_slider.setSliderPosition(pos)
def initSlider(self):
self.position_slider.setMaximum(self.player.duration())
self.position_slider.setToolTip("Позиция трека")
def initPlayer(self):
self.player = QMediaPlayer()
self.playlist = []
self.audio_output = QAudioOutput()
self.player.setAudioOutput(self.audio_output)
self.saved_volume = 0.5
self.audio_output.setVolume(self.saved_volume)
def initUI(self):
self.play_button = QPushButton("Play")
self.play_button.clicked.connect(self.play_music)
self.pause_button = QPushButton("Pause")
self.pause_button.clicked.connect(self.pause_music)
self.stop_button = QPushButton("Stop")
self.stop_button.clicked.connect(self.stop_music)
self.volume_slider = QSlider(Qt.Orientation.Horizontal)
self.volume_slider.setValue(50)
self.volume_slider.setMinimum(0)
self.volume_slider.setMaximum(100)
self.volume_slider.setToolTip("Volume")
self.volume_slider.valueChanged.connect(self.set_volume)
self.position_slider = QSlider(Qt.Orientation.Horizontal)
self.position_slider.setToolTip("Position")
# self.position_slider.sliderMoved.connect(self.set_position)
self.position_slider.sliderReleased.connect(self.on_slider_release)
self.backward_button = QPushButton("<< 10 sec")
self.backward_button.clicked.connect(self.backward_music)
self.forward_button = QPushButton("10 sec >>")
self.forward_button.clicked.connect(self.forward_music)
self.select_file_button = QPushButton("Add to playlist")
self.select_file_button.clicked.connect(self.select_file)
self.clear_playlist_button = QPushButton("Clear playlist")
self.clear_playlist_button.clicked.connect(self.clear_playlist)
self.playlist_widget = QListWidget()
self.playlist_widget.itemDoubleClicked.connect(self.play_selected_track)
self.track_label = QLabel("Track name")
vbox = QVBoxLayout()
hbox1 = QHBoxLayout()
hbox2 = QHBoxLayout()
hbox3 = QHBoxLayout()
hbox1.addWidget(self.play_button)
hbox1.addWidget(self.pause_button)
hbox1.addWidget(self.stop_button)
hbox1.addWidget(self.volume_slider)
hbox2.addWidget(self.backward_button)
hbox2.addWidget(self.position_slider)
hbox2.addWidget(self.forward_button)
hbox3.addWidget(self.track_label)
hbox3.addWidget(self.select_file_button)
hbox3.addWidget(self.clear_playlist_button)
vbox.addWidget(self.playlist_widget)
vbox.addLayout(hbox3)
vbox.addLayout(hbox1)
vbox.addLayout(hbox2)
self.setLayout(vbox)
def select_file(self):
folder_path = QFileDialog.getExistingDirectory(self, "Выбрать папку с музыкальными файлами", "")
if folder_path:
files = [os.path.join(folder_path, file) for file in os.listdir(folder_path) if
file.endswith(('.mp3', '.wav', '.ogg'))]
file_names = [file for file in os.listdir(folder_path) if file.endswith(('.mp3', '.wav', '.ogg'))]
for file in files:
self.playlist.append(file)
for file_name in file_names:
item = QListWidgetItem(file_name)
self.playlist_widget.addItem(item)
def play_music(self):
item = self.playlist_widget.currentItem()
index = self.playlist_widget.row(item)
if self.player.playbackState() == QMediaPlayer.PlaybackState.PausedState:
self.player.play()
else:
if (self.playlist):
url = QUrl.fromLocalFile(self.playlist[index]) # Создаем объект QUrl из строки с путем к файлу
self.player.durationChanged.connect(self.initSlider)
self.player.setSource(url)
self.audio_output.setVolume(self.saved_volume)
self.player.play()
def play_selected_track(self, item):
index = self.playlist_widget.row(item)
if 0 <= index < len(self.playlist):
url = QUrl.fromLocalFile(self.playlist[index])
self.player.setSource(url)
self.player.durationChanged.connect(self.initSlider)
self.audio_output.setVolume(self.saved_volume)
self.player.play()
def pause_music(self):
self.player.pause()
def stop_music(self):
self.player.stop()
def set_volume(self):
volume = self.volume_slider.value()
self.saved_volume = self.real_volume(volume)
self.audio_output.setVolume(self.saved_volume)
"""Метод конвертации значения слайдера (от 0 до 100)
к виду (от 0.0 до 1.0) и преобразование шкалы громкости
в логарифмическую(удобную для восприятия человеком)"""
def real_volume(self, slider_value):
return QAudio.convertVolume(
slider_value * .01,
QAudio.VolumeScale.LogarithmicVolumeScale,
QAudio.VolumeScale.LinearVolumeScale
)
def backward_music(self):
position_m = max(0, self.player.position() - 10000)
self.player.setPosition(position_m)
def forward_music(self):
position_m = min(self.player.duration(), self.player.position() + 10000)
self.player.setPosition(position_m)
def on_slider_release(self):
self.player.setPosition(self.position_slider.value())
def clear_playlist(self):
self.playlist_widget.clear()
self.playlist.clear()
app = QApplication(sys.argv)
playerM = MusicPlayer()
playerM.show()
sys.exit(app.exec())
我想在选择新曲子之前重置源,但我没有找到相关的命令。我希望能够在不崩溃的情况下切换曲子。我还注意到它在第180行: self.player.setSource(url)崩溃了。
1 个回答
0
我找到了一种解决办法。在我设置新的音源之前,我会先停止播放器,然后检查播放器是否已经停止。接着,我会用一个延迟调用一个函数,这个延迟是通过QTimer.singleShot来实现的。
self.player.stop()
if self.player.playbackState() == QMediaPlayer.PlaybackState.StoppedState:
QTimer.singleShot(1, lambda: self.source_setter(url))
def source_setter(self, url):
self.player.setSource(url)
self.player.play()