提示未连接到pulseaudio服务
1 个赞
有没有高手解答一下,我也遇到了这个问题
1.可以提供一下硬件设备信息和软件版本信息方便排查
2.检查 PulseAudio 进程是否存在,检查是否端口占用
暂时音频在受权限受限的设备上还不支持
- 安装
pulseaudio
、pulseaudio-enable-autospawn
、libpulse0
等与 pulseaudio 相关的软件包。 - 使用命令编辑配置文件:
nano /data/data/com.aidlux/files/usr/etc/pulse/default.pa
在 default.pa
文件中插入以下内容(或去掉前面的 #
注释符号),然后保存文件:
load-module module-aaudio-sink
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1 --exit-idle-time=-1
- 在终端中执行以下命令,取消
PULSE_SERVER
的设置:
unset PULSE_SERVER
- 在你的
.zshrc
、.bashrc
等 shell 配置文件中加入以下内容:
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export TMPDIR=/tmp
bash ~/.startaudio
- 创建
~/.startaudio
文件,并写入以下脚本内容。保存后使用chmod +x ~/.startaudio
使其可执行。
每次登录 Aidlux 时,PulseAudio 将自动启动。
#!/bin/bash
# 防止重复运行
if pgrep -x "pulseaudio" > /dev/null; then
exit 0
fi
# 静默结束已存在的 PulseAudio 实例
pkill -f pulseaudio >/dev/null 2>&1
# 检查 DBus 是否正在运行且未退出
if ! pgrep -x "dbus-daemon" > /dev/null || ! busctl --list | grep -q "org.freedesktop.DBus"; then
service dbus restart >/dev/null 2>&1
dbus-launch --exit-with-session >/dev/null 2>&1
fi
# 后台启动 PulseAudio(静默)
service pulseaudio-enable-autospawn start >/dev/null 2>&1
nohup /data/data/com.aidlux/files/usr/bin/pulseaudio \
--start --load="module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1" --exit-idle-time=-1 \
>/dev/null 2>&1 &
exit 0
- 确保你已经删除/卸载所有 ALSA 相关的软件包,并删除 ALSA 的配置文件(
alsa_conf
),因为它们会与 PulseAudio 冲突。
你也可以使用如下命令阻止 ALSA 软件包被重新安装:
sudo apt-mark hold <alsa软件包名称>
- 可使用以下命令将
module-aaudio-sink
设置为默认的输出设备(sink):
bash /data/data/com.aidlux/files/usr/bin/pactl set-default-sink module-aaudio-sink
如果没有任何反应,尝试重启系统后再尝试。
- 第一次设置完成后,记得执行以下命令重启设备:
aid-reboot
- 重启之后,可以通过以下命令测试 PulseAudio 是否正常启动:
pulseaudio -vvv
- PulseAudio 无法启动的常见原因是 DBus 和 ALSA 配置问题。如果遇到问题,请解决后重启设备。
另一种跟简单的方法如下:
AidLux 音频播放器与 SL4A 集成版
这是一个功能丰富的音频播放器,专为运行 AidLux 的 Android 设备设计,利用 Android 脚本层(SL4A)实现媒体控制。该脚本提供基于终端的音频播放控制,支持播放列表、随机播放、循环播放和音量调节等功能。
功能特点:
- 可直接播放音频文件或文件夹中的音频
- 支持多种音频格式(MP3、WAV、OGG、M4A、FLAC、AAC)
- 带键盘控制的交互式终端界面
- 播放控制(播放/暂停、上一曲/下一曲)
- 音量调节
- 支持随机播放与循环播放模式
- 显示播放进度
- 优雅地处理系统信号中断
键盘控制:
p
:暂停播放r
:恢复播放n
:下一首b
:上一首l
:切换循环模式h
:切换随机播放模式+
:增加音量-
:降低音量q
:退出播放器
请安装:
- FFmpeg(用于检测音频时长)
使用方法:
python3.8 aidlux-sl4a.py <文件或目录路径>
示例:
python3 aidluxsl4a.py /sdcard/Music
python3 aidluxsl4a.py /sdcard/Music/song.mp3
代码如下:
#!/usr/bin/env python3
import os
import random
import select
import signal
import subprocess
import sys
import termios
import threading
import time
import tty
import android
# Initialize AidLux API
droid = android.Android()
class PlayerState:
"""Manages the state of the audio player."""
def __init__(self):
self.playlist = []
self.current_index = 0
self.looping = False
self.shuffle_mode = False
self.progress_stop_flag = threading.Event()
self.progress_thread = None
self.paused = False
self.running = True
self.current_start_time = 0
self.current_duration = 0
state = PlayerState()
def load_audio(path):
"""Load and play a file or folder."""
if os.path.isfile(path):
state.playlist = [path]
elif os.path.isdir(path):
valid_ext = (".mp3", ".wav", ".ogg", ".m4a", ".flac", ".aac")
state.playlist = sorted(
os.path.join(path, f) for f in os.listdir(path) if f.endswith(valid_ext)
)
if not state.playlist:
print("\n🚫 No audio files found.")
return
else:
print("\n🚫 Invalid path.")
sys.exit(1)
print(f"\n🎶 Playing {len(state.playlist)} files from {path}")
state.current_index = 0
play_audio()
def get_audio_duration(file_path):
"""Get the duration of the audio file using ffmpeg."""
try:
result = subprocess.run(
["ffmpeg", "-i", file_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
for line in result.stderr.splitlines():
if "Duration" in line:
duration_str = line.split("Duration:")[1].split(",")[0].strip()
hours, minutes, seconds = duration_str.split(":")
return int(hours) * 3600 + int(minutes) * 60 + float(seconds)
return 0
except Exception:
return 0
def format_time(seconds):
"""Convert seconds to HH:MM:SS format."""
hours = int(seconds // 3600)
minutes = int((seconds % 3600) // 60)
seconds = int(seconds % 60)
return f"{hours:02}:{minutes:02}:{seconds:02}"
def show_playback_progress(start_time, total_duration):
"""Display playback progress."""
last_position = -1
try:
while not state.progress_stop_flag.is_set() and total_duration > 0:
if state.paused:
time.sleep(0.5)
continue
current_position = time.time() - start_time
# Only update display if position changed by at least 1 second
if int(current_position) != last_position:
last_position = int(current_position)
sys.stdout.write(
f"\r⏱️ {format_time(current_position)} / {format_time(total_duration)} "
)
sys.stdout.flush()
if current_position >= total_duration:
if not state.looping:
print("\n🎵 Finished.")
next_song()
break
time.sleep(0.5) # More responsive updates
except Exception as e:
print(f"\n⚠️ Error in progress tracking: {str(e)}")
finally:
# Clear the line when done
sys.stdout.write("\r" + " " * 50 + "\r")
sys.stdout.flush()
def stop_playback():
"""Stop any ongoing playback and clean up resources."""
if state.progress_thread and state.progress_thread.is_alive():
state.progress_stop_flag.set()
state.progress_thread.join(timeout=0.5)
state.progress_thread = None
droid.mediaPlayClose()
time.sleep(0.2) # Small delay to ensure clean state
def play_audio():
"""Play the current song."""
if not state.playlist:
print("\n🚫 Playlist is empty.")
return
# Stop any existing playback and clean up
stop_playback()
file_path = state.playlist[state.current_index]
print(f"\n🎵 Now playing: {os.path.basename(file_path)}")
# Reset the stop flag for the new playback
state.progress_stop_flag.clear()
# Start new playback
droid.mediaPlay(file_path)
# Get duration and set up progress tracking
state.current_duration = get_audio_duration(file_path)
state.current_start_time = time.time()
# Start new progress thread
state.progress_thread = threading.Thread(
target=show_playback_progress,
args=(state.current_start_time, state.current_duration),
daemon=True
)
state.progress_thread.start()
def pause_audio():
"""Pause playback."""
if not state.paused:
droid.mediaPlayPause()
print("\n⏸️ Paused playback.")
state.paused = True
def resume_audio():
"""Resume playback."""
if state.paused:
droid.mediaPlayStart()
print("\n▶️ Resumed playback.")
state.paused = False
# Update start time to account for pause duration
state.current_start_time = time.time() - (time.time() - state.current_start_time - (time.time() % 1))
def next_song():
"""Play the next song."""
if state.current_index < len(state.playlist) - 1:
state.current_index += 1
play_audio()
else:
print("\n⏹️ End of playlist reached.")
def previous_song():
"""Play the previous song."""
if state.current_index > 0:
state.current_index -= 1
play_audio()
def toggle_loop():
"""Toggle looping mode."""
state.looping = not state.looping
droid.mediaPlaySetLooping(state.looping)
print(f"\n🔁 Looping {'on' if state.looping else 'off'}")
def toggle_shuffle():
"""Toggle shuffle mode."""
state.shuffle_mode = not state.shuffle_mode
if state.shuffle_mode:
random.shuffle(state.playlist)
else:
state.playlist.sort()
print(f"\n🔀 Shuffle {'on' if state.shuffle_mode else 'off'}")
def adjust_volume(change):
"""Adjust media volume."""
current_vol = droid.getMediaVolume().result
new_vol = max(0, min(15, current_vol + change))
droid.setMediaVolume(new_vol)
print(f"\n🔊 Volume set to {new_vol}")
def handle_exit_signal(sig, frame):
"""Handle exit signal."""
print("\n👋 Exiting...")
stop_playback()
sys.exit(0)
def process_key(key):
"""Process key commands."""
key = key.lower()
if key == "p":
pause_audio()
elif key == "r":
resume_audio()
elif key == "n":
next_song()
elif key == "b":
previous_song()
elif key == "l":
toggle_loop()
elif key == "h":
toggle_shuffle()
elif key == "+":
adjust_volume(1)
elif key == "-":
adjust_volume(-1)
elif key == "q":
droid.mediaPlayClose()
state.running = False
return False
return True
if __name__ == "__main__":
signal.signal(signal.SIGINT, handle_exit_signal) # Handle Ctrl+C gracefully
if len(sys.argv) < 2:
print("Usage: python3 audio.py <file or folder>")
sys.exit(1)
load_audio(sys.argv[1]) # Load and start playing audio
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setcbreak(fd)
running = True
while running:
try:
if select.select([sys.stdin], [], [], 0)[0]:
key = sys.stdin.read(1)
running = process_key(key)
time.sleep(0.1)
except KeyboardInterrupt:
handle_exit_signal(None, None) # Handle Ctrl+C
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)