Я загружаю плейлист, нажимая «Добавить в плейлист». Когда я нажимаю на любой элемент в списке, плеер работает нормально. Но если я попытаюсь выбрать другой трек в списке, программа вылетит. Я заметил следующие факторы:
Я пытался это исправить, но это не сработало. Заранее спасибо.
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)
Я удалил все соединения и отключил таймер, но он все равно вылетает. Также я заметил сбой в строке 180: self.player.setSource(url)
Затем попробуйте запустить программу в терминале или командной строке и посмотрите, отображает ли она какой-либо отладочный вывод. Если это так, но вы все еще не можете понять, что является причиной этого, пожалуйста, отредактируйте свой вопрос и покажите нам этот результат.
Я нашел какое-то решение. Прежде чем установить новый источник для воспроизведения, я останавливаю проигрыватель, а затем проверяю, остановлен ли проигрыватель. После этого я вызываю функцию с задержкой, используя QTimer.singleShot.
Это лишь частичное решение, так как это может быть ошибка, и нам следует знать о ней больше, но мы не можем сделать это без дополнительной информации. Вы сделали то, что предложили выше?






Я нашел какое-то решение. Прежде чем установить новый источник для воспроизведения, я останавливаю проигрыватель, а затем проверяю, остановлен ли проигрыватель. После этого я вызываю функцию с задержкой, используя 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()
Я бы начал с удаления ненужных подключений, которые могут и не иметь отношения к реальной проблеме, но уж точно не подходят: например, вам следует подключиться к
durationChangedтолько один раз, а сейчас вы подключаетесь каждый раз, когда загружается новый файл. , что явно бесполезно. Кроме того, проверять положение ползунка каждую миллисекунду совершенно бессмысленно и неправильно: просто используйте соответствующие сигналы и возможности, предоставляемые QAbstractSlider.