You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python监听Spotify切歌事件的信号重复、延迟及弃用警告问题

实现目标

本人仅有约两天编程经验,目标是开发一款程序,实现Spotify每次切换歌曲时自动触发对应快捷键。参考相关论坛内容拼凑出初始代码如下:

#!/usr/bin/env python3
# encoding: utf-8

BUS_NAME='org.mpris.MediaPlayer2.spotify'

import subprocess
import dbus, urllib.request
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GObject

def dbus_signal_receiver(interface, changes, sig):
   if dbus.String('Metadata') in changes:
       subprocess.run(["/home/user/Scripts/shortcut.sh"])

if __name__ == '__main__':
   DBusGMainLoop(set_as_default=True)
   bus = dbus.SessionBus()
   bus.add_signal_receiver(dbus_signal_receiver, path='/org/mpris/MediaPlayer2', bus_name=BUS_NAME)
   loop = GObject.MainLoop()
   loop.run() 
现存问题
  • 运行程序时抛出弃用警告,已知警告含义但不会修复,当前程序可正常运行,警告内容如下:
/home/lorenz/Scripts/LatestApproach.py:23: PyGIDeprecationWarning: GObject.MainLoop is deprecated; use GLib.MainLoop instead
  loop = GObject.MainLoop()
  • 切歌时DBus会重复输出6次变更信号,导致快捷键在1秒内被触发6次。之前尝试通过time.sleep添加2秒延迟,最终变成每2秒固定触发一次快捷键,不符合预期。
修复方案

修复弃用警告

直接替换弃用的GObject主循环为GLib主循环即可:

  1. 将导入语句from gi.repository import GObject替换为from gi.repository import GLib
  2. 将主循环初始化语句loop = GObject.MainLoop()替换为loop = GLib.MainLoop()

修复信号重复触发问题

不要用sleep做延迟,这种方式会阻塞事件循环,排队的信号会等sleep结束后依次执行,还是会重复触发。正确的做法是通过歌曲唯一ID做去重:

  1. 定义变量记录上一次成功触发脚本时对应的歌曲Track ID
  2. 每次收到Metadata变更信号时,先提取当前播放歌曲的唯一Track ID
  3. 只有当当前Track ID和上一次记录的ID不一致时,才执行快捷键脚本,同时更新记录的ID;ID一致直接跳过处理即可

修复后的完整代码:

#!/usr/bin/env python3
# encoding: utf-8

BUS_NAME='org.mpris.MediaPlayer2.spotify'
MPRIS_PATH = '/org/mpris/MediaPlayer2'

import subprocess
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib

# 记录上一次处理的歌曲ID,初始为空
last_track_id = ""

def dbus_signal_receiver(interface, changes, sig):
    global last_track_id
    if 'Metadata' in changes:
        metadata = changes['Metadata']
        # 提取当前歌曲的唯一Track ID
        current_track_id = metadata.get('mpris:trackid', '')
        # ID和上次不同才触发脚本
        if current_track_id and current_track_id != last_track_id:
            last_track_id = current_track_id
            subprocess.run(["/home/user/Scripts/shortcut.sh"])

if __name__ == '__main__':
    DBusGMainLoop(set_as_default=True)
    bus = dbus.SessionBus()
    bus.add_signal_receiver(
        dbus_signal_receiver,
        path=MPRIS_PATH,
        bus_name=BUS_NAME,
        signal_name='PropertiesChanged'
    )
    loop = GLib.MainLoop()
    loop.run()

注:代码里删掉了未使用的urllib.request导入,同时明确指定监听PropertiesChanged信号,避免接收无关信号增加不必要的判断。


内容的提问来源于stack exchange,提问作者Atomfried Fallout

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:24:26