QtMultimedia 播放聲音或音樂
QtMultimedia 是 PyQt6 裡負責播放多媒體影音的元件,使用其中的 QMediaPlayer 方法就能建立播放器,播放指定位址的影片或聲音,這篇教學會介紹如何在 PyQt6 視窗裡加入 QtMultimedia 元件並播放聲音,最後會實作一個簡單的音樂播放器。
快速導覽:
因為 Google Colab 不支援 PyQt6,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda )。
QtMultimedia 播放聲音或音樂
建立 PyQt6 視窗物件後,透過 QtMultimedia.QMediaPlayer()
方法,就能建立播放器物件,再透過 QtMultimedia.QAudioOutput()
建立音樂輸出器,將兩者綁定後就能使用對應的方法播放聲音,下方的程式碼執行後,開啟視窗就會播放聲音。
注意聲音的路徑必須與執行的 Python 路徑相同,並透過 QUrl 轉換成指定的格式。
from PyQt6 import QtWidgets
from PyQt6.QtCore import *
from PyQt6.QtMultimedia import *
import sys, os
app = QtWidgets.QApplication(sys.argv)
main = QtWidgets.QMainWindow()
main.setObjectName("MainWindow")
main.setWindowTitle("oxxo.studio")
main.resize(300, 300)
player = QMediaPlayer() # 建立播放器
path = os.getcwd() + '/' # 取得目前工作路徑
qurl = QUrl.fromLocalFile(path+'test.mp3') # 取得音樂路徑
audio_output = QAudioOutput() # 建立音樂輸出器
player.setAudioOutput(audio_output) # 播放器與音樂輸出器綁定
player.setSource(qurl) # 建立音樂內容
audio_output.setVolume(100) # 設定音量
player.play() # 播放
main.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets, QtCore, QtMultimedia
import sys, os
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.playMusic()
def playMusic(self):
self.player = QtMultimedia.QMediaPlayer() # 建立播放器
self.path = os.getcwd() + '/' # 取得目前工作路徑
self.qurl = QtCore.QUrl.fromLocalFile(self.path+'test.mp3') # 取得音樂路徑
self.audio_output = QtMultimedia.QAudioOutput() # 建立音樂輸出器
self.player.setAudioOutput(self.audio_output) # 播放器與音樂輸出器綁定
self.player.setSource(self.qurl) # 建立音樂內容
self.audio_output.setVolume(100) # 設定音量
self.player.play() # 播放
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
QMediaPlayer() 播放器常用方法
建立播放器之後,就能使用播放器的方法操作聲音檔案,下方列出常用的操作與設定方法:
方法 | 參數 | 說明 |
---|---|---|
play() | 播放。 | |
pause() | 暫停。 | |
stop() | 停止。 | |
setMedia() | QUrl | 設定播放媒體檔案。 |
setPlaybackRate() | float | 設定播放速度,預設 1.0 正常,數值越小越慢。 |
setMuted() | bool | 設定靜音,True 靜音,False 取消靜音。 |
setPosition() | bool | 設定播放的毫秒數 ( ms )。 |
setPlaylist() | QMediaPlaylist() | 設定播放清單。 |
取得媒體資訊的常用方法:
方法 | 說明 |
---|---|
duration() | 聲音檔案的總毫秒數 ( ms )。 |
position() | 目前播放位置的毫秒數 (ms)。 |
playbackRate() | 目前播放速度。 |
state() | 目前播放狀態,0 為停止,1 為播放,2 為暫停。 |
volume() | 前的音量大小。 |
currentMedia() | .canonicalUrl().fileName() 目前的檔案,.playlist().currentIndex() 目前播放清單的號碼。 |
isMuted() | 目前是否靜音。 |
媒體觸發事件的常用方法,通常會再搭配 connect 串接對應的函式:
方法 | 說明 |
---|---|
mutedChanged | 當靜音狀態改變。 |
durationChanged | 當聲音長度發生改變。 |
currentMediaChanged | 當來源發生改變 ( 播放清單 )。 |
mediaChanged | 當來源發生改變。 |
volumeChanged | 當音量改變。 |
stateChanged | 當播放狀態改變。 |
positionChanged | 當播放位置改變。 |
playbackRateChanged | 當播放速度改變。 |
簡單的音樂播放器
在畫面中加入一些 QLabel 和 QPushButton,就能透過 QMediaPlayer() 的各種方法,做出一個簡單的音樂播放器,詳細的說明寫在下方的程式碼中。
from PyQt6 import QtWidgets
from PyQt6.QtCore import *
from PyQt6.QtMultimedia import *
import sys, os
app = QtWidgets.QApplication(sys.argv)
main = QtWidgets.QMainWindow()
main.setObjectName("MainWindow")
main.setWindowTitle("oxxo.studio")
main.resize(300, 300)
label = QtWidgets.QLabel(main) # 放入 QLabel 顯示時間
label.setGeometry(210, 30, 100, 30) # 設定位置
label.setText('0.0 / 0.0') # 預設顯示文字
# 點擊播放按鈕的程式
def f1():
btn1.setDisabled(True) # 停用播放按鈕
btn2.setDisabled(False) # 啟用暫停按鈕
btn3.setDisabled(False) # 啟用停止按鈕
player.play() # 播放聲音
# 點擊暫停按鈕的程式
def f2():
btn1.setDisabled(False) # 啟用播放按鈕
btn2.setDisabled(True) # 停用暫停按鈕
btn3.setDisabled(False) # 啟用停止按鈕
player.pause() # 暫停聲音
# 點擊停止按鈕的程式
def f3():
btn1.setDisabled(False) # 啟用播放按鈕
btn2.setDisabled(False) # 啟用暫停按鈕
btn3.setDisabled(True) # 停用停止按鈕
player.stop() # 停止聲音
btn1 = QtWidgets.QPushButton(main) # 放入播放按鈕
btn1.setText('播放') # 設定文字
btn1.setGeometry(25, 30, 60, 30) # 設定位置
btn1.setDisabled(True) # 預設停用
btn1.clicked.connect(f1) # 連接 f1 程式
btn2 = QtWidgets.QPushButton(main) # 放入暫停按鈕
btn2.setText('暫停') # 設定文字
btn2.setGeometry(75, 30, 60, 30) # 設定位置
btn2.clicked.connect(f2) # 連接 f2 程式
btn3 = QtWidgets.QPushButton(main) # 放入停止按鈕
btn3.setText('停止') # 設定文字
btn3.setGeometry(125, 30, 60, 30) # 設定位置
btn3.clicked.connect(f3) # 連接 f3 程式
slider = QtWidgets.QSlider(main) # 放入調整滑桿
slider.setOrientation(Qt.Orientation.Horizontal) # 設定水平顯示
slider.setGeometry(30, 60, 240, 30) # 設定位置
slider.setRange(0, 100) # 設定預設範圍
slider.setValue(50) # 設定預設值
slider.sliderMoved.connect(lambda: player.setPosition(slider.value())) # 當滑桿移動時,設定播放器的播放位置
player = QMediaPlayer() # 設定播放器
path = os.getcwd() # 取得音樂檔案路徑
qurl = QUrl.fromLocalFile(path+'/test.mp3') # 轉換成 QUrl
audio_output = QAudioOutput() # 建立音樂輸出器
player.setAudioOutput(audio_output) # 播放器與音樂輸出器綁定
player.setSource(qurl) # 設定音樂內容
player.durationChanged.connect(lambda: slider.setMaximum(player.duration())) # 當總長度改變時,設定滑桿的最大值
player.play() # 播放音樂
# 播放器的函式
def playmusic():
progress = player.position() # 取的目前播放時間
slider.setValue(progress) # 設定滑桿位置
label.setText(f'{str(round(progress/1000, 1))} / {str(round(player.duration()/1000, 1))}') # 文字顯示
timer = QTimer() # 加入定時器
timer.timeout.connect(playmusic) # 設定定時要執行的 function
timer.start(1000) # 啟用定時器,設定間隔時間為 500 毫秒
main.show()
sys.exit(app.exec())
同樣的結果也可以改用 class,寫法如下:
from PyQt6 import QtWidgets
from PyQt6.QtCore import *
from PyQt6.QtMultimedia import *
import sys, os
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setObjectName("MainWindow")
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.ui()
self.run()
def ui(self):
self.label = QtWidgets.QLabel(self)
self.label.setText('0.0 / 0.0')
self.label.setGeometry(210, 30, 100, 30)
self.btn1 = QtWidgets.QPushButton(self)
self.btn1.setText('播放')
self.btn1.setGeometry(25, 30, 60, 30)
self.btn1.setDisabled(True)
self.btn1.clicked.connect(self.f1)
self.btn2 = QtWidgets.QPushButton(self)
self.btn2.setText('暫停')
self.btn2.setGeometry(75, 30, 60, 30)
self.btn2.clicked.connect(self.f2)
self.btn3 = QtWidgets.QPushButton(self)
self.btn3.setText('停止')
self.btn3.setGeometry(125, 30, 60, 30)
self.btn3.clicked.connect(self.f3)
self.slider = QtWidgets.QSlider(self)
self.slider.setOrientation(Qt.Orientation.Horizontal)
self.slider.setGeometry(30, 60, 240, 30)
self.slider.setRange(0, 100)
self.slider.setValue(50)
self.slider.sliderMoved.connect(lambda: self.player.setPosition(self.slider.value()))
self.player = QMediaPlayer() # 設定播放器
self.path = os.getcwd() # 取得音樂檔案路徑
self.qurl = QUrl.fromLocalFile(self.path+'/test.mp3') # 轉換成 QUrl
self.audio_output = QAudioOutput()
self.player.setAudioOutput(self.audio_output) # 播放器與音樂輸出器綁定
self.player.setSource(self.qurl)
self.player.durationChanged.connect(lambda: self.slider.setMaximum(self.player.duration()))
self.player.play()
def f1(self):
self.btn1.setDisabled(True)
self.btn2.setDisabled(False)
self.btn3.setDisabled(False)
self.player.play()
def f2(self):
self.btn1.setDisabled(False)
self.btn2.setDisabled(True)
self.btn3.setDisabled(False)
self.player.pause()
def f3(self):
self.btn1.setDisabled(False)
self.btn2.setDisabled(False)
self.btn3.setDisabled(True)
self.player.stop()
def playmusic(self):
progress = self.player.position()
self.slider.setValue(progress)
self.label.setText(f'{str(round(progress/1000, 1))} / {str(round(self.player.duration()/1000, 1))}')
def run(self):
self.timer = QTimer() # 加入定時器
self.timer.timeout.connect(self.playmusic) # 設定定時要執行的 function
self.timer.start(1000) # 啟用定時器,設定間隔時間為 500 毫秒
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~