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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:42:47