如何在Zsh/Bash中实现带按键控制的MP3播放器?
Zsh/Bash 实现支持“n”键切歌的MP3播放器
问题根源
你的代码里ffplay -autoexit是前台独占终端运行,只有等歌曲播放完毕,脚本才会执行到read命令。播放过程中所有按键输入都被ffplay接管,而ffplay默认的n键并不是切换下一首的快捷键,所以完全没效果。
解决方案
下面提供两种可行方案,推荐用mpv(更省心),也可以改进ffplay的脚本逻辑。
方案一:改用mpv播放器(推荐)
mpv是专门为脚本控制设计的媒体播放器,默认支持n键切换下一首,无需自己写复杂的按键监听逻辑:
mp3_player() { # 确保当前目录仅包含MP3文件 local idx=$1 local files=(*) # 校验起始索引合法性 if (( idx < 1 || idx > ${#files[@]} )); then echo "起始索引无效,范围是 1-${#files[@]}" return 1 fi # 从指定索引开始播放,mpv默认按n切下一首 mpv --playlist-start=$((idx - 1)) "${files[@]}" }
注:mpv的播放列表索引从0开始,所以要把传入的idx减1。运行后按n直接切下一首,按q退出播放器。
方案二:改进ffplay脚本,后台运行+按键监听
如果坚持用ffplay,可以把它后台运行,同时脚本在前台监听按键,按下n时杀死当前播放进程并切换下一首:
mp3_player() { local idx=$1 local files=(*) local ffplay_pid local key="" # 校验起始索引 if (( idx < 1 || idx > ${#files[@]} )); then echo "起始索引无效,范围是 1-${#files[@]}" return 1 fi while :; do # 索引超出范围时循环到第一首 if (( idx > ${#files[@]} )); then idx=1 fi echo "正在播放: ${files[$((idx))]}" # 后台运行ffplay,禁用窗口和视频流(播放MP3无需) ffplay -autoexit -nodisp -vn "${files[$((idx))]}" & ffplay_pid=$! # 监听按键,直到ffplay结束或按下n while kill -0 $ffplay_pid 2>/dev/null; do read -t 0.1 -k 1 key if [[ $key == "n" ]]; then kill $ffplay_pid key="" break fi done idx=$((idx + 1)) done }
说明:-nodisp关闭ffplay的窗口,-vn跳过视频流处理,减少资源占用。按下n会立即终止当前播放并切换下一首,歌曲自然播放完毕也会自动切换下一首。
内容的提问来源于stack exchange,提问作者ecjb
相关产品推荐
相关产品推荐

