Как извлечь длительность аудиофайла с помощью PyQt 5?(часть 2)
UPD: Мне не нужно воспроизводить песни, пути к которым я получаю. Мне нужно извлечь из них длину и не более
Я уже задавал такой вопрос здесь, но, чтобы сделать ситуацию проще, я попытался отбросить все моменты, о которых, как потом оказалось, нужно было рассказать.
Сейчас я попытаюсь объяснить, что происходит и что мне нужно.
Кнопка play_btn взаимодействует с методом play, который запускает воспроизведение какой-нибудь песни. Я кликаю по ней.
Кнопка folder_btn связана с методом choose_folder, который совершает некоторые манипуляции с файлами:
- Открывает диалоговое окно выбора папки с файлами
- Отбирает из выбранной папки файлы MP3-формата
- Немного изменяет путь к этим файлам, чтобы было проще работать с PyQt
- Создает соединение с базой данных, куда будет записываться информация о треке
Все эти пункты не играют никакой роли в моем вопросе, поэтому я вырезал их из кода. В конечном итоге я
получаю список, содержащий пути к MP3-файлам. Я дал ему название songs.
Получив пути к файлам, нужно достать и записать длительность каждого в self.list. При этом play_btn уже нажата, а значит, приложение уже воспроизводит звук. Если добавлять файлы из songs в QMediaPlayer, песня, котороя уже воспроизводилась плеером, собьется. Поэтому в прошлом вопросе я говорил о том, что не могу задавать новый источник звука плееру.
Пожалуйста, скажите, как извлечь длительность аудиофайлов в моем случае?
from PyQt5 import QtCore, QtWidgets, QtGui, QtMultimedia
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__(parent)
self.list = [] # сюда нужно записать длину аудиофайлов
self.player = QtMultimedia.QMediaPlayer()
box = QtWidgets.QHBoxLayout(self)
play_btn = QtWidgets.QPushButton('Play', clicked = self.play)
box.addWidget(play_btn)
folder_btn = QtWidgets.QPushButton('New Folder', clicked = self.choose_folder)
box.addWidget(folder_btn)
def play(self):
self.song = 'C:/Users/User/Desktop/music/8.Figure09.mp3'
self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl(self.song)))
self.player.play()
def choose_folder(self):
# тут происходит выбор директории с аудиофайлами
songs = ['C:/Users/User/Desktop/music/13.Numb.mp3',
'C:/Users/User/Desktop/music/10.From the Inside.mp3']
# в итоге я получаю такой список ^^^
self.extract_length(songs)
def extract_length(self, songs):
pass
# тут нужно извлечь длину аудиофайлов из self.songs и записать в self.list
# при этом self.player уже будет воспроизводить звук
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.setWindowTitle(' ')
window.show()
sys.exit(app.exec_())
Возможно, я мог что-то неправильно понять. Возможно, я что-то плохо объяснил. Пожалуйста, напишите, если что-то не так
Ответы (2 шт):
Вообще, извлечение длительности проигрывания медиа-файла (duration) до начала воспроизведения для Qt, задача не тривиальная. Но можно попробовать один Qt-hack:
def extract_length(self, songs):
# В процессе получения длительностей можно/нужно
# заблокировать соответствующие виджеты интерфейса,
# чтобы исключить вмешательство пользователя в процесс
# получения длительностей медиа-файлов
songs = ['C:/Users/User/Desktop/music/13.Numb.mp3',
'C:/Users/User/Desktop/music/10.From the Inside.mp3']
playlist = player.playlist()
if not playlist:
playlist = QMediaPlaylist()
# Текущее количество элементов в листе
# для пустого и нового 0
pos = playlist.mediaCount()
# Наполняем плейлист
for song in songs:
playlist.addMedia(QMediaContent(QUrl(song)))
player.setPlaylist(playlist)
# устанавливаем текущий индекс файла в листа
# для получения длительностей
player.playlist().setCurrentIndex(pos)
player.durationChanged.connect(self.fileDuration)
# Убираем звук
player.setMuted(true)
# Стартуем программное проигрывание файлов из плейлиста
player.play()
def fileDuration(self, duration_value):
cur_index = player.playlist().currentIndex()
if cur_index >= player.playlist().mediaCount():
# дисконектимся от слота
player.durationChanged.disconnect(self.fileDuration)
# останавливаем программное проигрывание файлов
player.stop()
# Разблокируем виджеты интерфейса
else:
# по текущему индексу cur_index (например в QListWidget)
# записываем текущее значение duration_value
...
# вызываем следующий медиа-файл из медиа-списка
player.playlist().next()
Я не понимаю зачем вы пишите в БД информацию о длительност песни, она рассчитывается мгновенно и это по моему излишнее.
Где вы прочитали, что вы не можете создавать новый источник звука плееру?
Обратите внимание на объект player2.
В моем примере вы увидите два варианта получения длительность аудиофайлов:
- метод
time_duration; - метод
time_duration2.
Обратите внимание как эти методы вызываются.
Я увидел вашу задачу так:
from PyQt5 import QtCore, QtWidgets, QtGui, QtMultimedia
class MyWindow(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__(parent)
self.list = [] # сюда нужно записать длину аудиофайлов
self.player = QtMultimedia.QMediaPlayer()
self.player.durationChanged.connect(self.time_duration) # +++
play_btn = QtWidgets.QPushButton('Play', clicked = self.play)
folder_btn = QtWidgets.QPushButton('New Folder', clicked = self.choose_folder)
# self.options - какой-то список существующей музыки, которуй можно выбирать и проигрывать
self.list_widget = QtWidgets.QListWidget() # +++
self.options = ['D:/_Qt/__Qt/sound/sound_ringtimer.mp3',
'D:/_Qt/EXE/Mp3/new_build/QThread_mp3/img/zvuki_prirody.mp3']
self.list_widget.addItems([ s.split('/')[-1] for s in self.options ])
self.list_widget.currentRowChanged.connect(self.on_itemClicked)
self.row = 0 # индекс строки списка options, кот. можео проигрывать
box = QtWidgets.QGridLayout(self)
box.addWidget(self.list_widget, 0, 0, 1, 2)
box.addWidget(play_btn, 1, 0)
box.addWidget(folder_btn, 1, 1)
def on_itemClicked(self, row):
self.row = row # мы выбрали другию стороку
def time_duration(self, d):
m = d // 1000 // 60
s = d // 1000 % 60
# Pедактируем выбранный элемент списка QListWidget
itemNumber = self.list_widget.currentRow()
item = self.list_widget.item(itemNumber)
if f'{m:>1}:{s:0>2}' != '0:00' and item.text()[-1] != '.':
text = f'{item.text()} -> {m:>1}:{s:0>2}.'
item.setText(text)
def play(self):
self.song = self.options[self.row]
self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl(self.song)))
self.player.play()
def choose_folder(self):
# тут происходит выбор директории с аудиофайлами
songs = ['D:/_Qt/__Qt/bibi.mp3',
'D:/_Qt/__Qt/sound/sound_ringtimer.mp3',
'D:/_Qt/EXE/Mp3/new_build/QThread_mp3/img/zvuki_prirody.mp3',
'D:/_Qt/__Qt/bibi.mp3',]
# в итоге я получаю такой список ^^^
self.extract_length(songs)
def extract_length(self, songs):
# pass
# тут нужно извлечь длину аудиофайлов из self.songs и записать в self.list
# при этом self.player уже будет воспроизводить звук
for song in songs:
player2 = QtMultimedia.QMediaPlayer() # ! player2
player2.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl(song)))
player2.play()
player2.setVolume(0.0)
QtCore.QTimer.singleShot(150, lambda p=player2, song=song: self.time_duration2(p, song))
def time_duration2(self, p, song): #d):
d = p.duration()
m = d // 1000 // 60
s = d // 1000 % 60
# Добавляем элементы в список QListWidget
item = QtWidgets.QListWidgetItem()
item.setText(f'{song.split("/")[-1]} - {m:>1}:{s:0>2} -> {d}')
self.list_widget.addItem(item)
self.options.append(song)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.setWindowTitle(' ')
window.show()
sys.exit(app.exec_())
