如何实时截获独立shell中命令的输出并通过say实时朗读LLM回复?
如何实时截获独立shell中命令的输出并通过say实时朗读LLM回复?
嘿,我懂你的困扰——用ollama run llama3:latest | tee >(say)的时候,say非要等整个会话结束才一次性把所有内容读出来,完全做不到LLM回复一句就读一句,对吧?其实这跟“独立shell”关系不大,核心问题是标准输出的缓冲机制:当命令的输出被导向管道时,很多程序会切换成“块缓冲”模式,攒够一大块内容才会输出,而不是实时把每一行/每一段内容送出来。
给你几个实用的解决办法,亲测有效的那种:
方法一:用stdbuf关闭输出缓冲
这是最直接的方式,stdbuf可以强制命令关闭输入、输出、错误流的缓冲,让内容实时通过管道传递:
stdbuf -i0 -o0 -e0 ollama run llama3:latest | tee >(say)
参数解释:-i0关闭输入缓冲,-o0关闭输出缓冲,-e0关闭错误缓冲,这样ollama的每一段输出都会立刻传给tee和say,实现实时朗读。
方法二:用unbuffer模拟交互式终端
如果你的系统里没有stdbuf,可以试试unbuffer(需要先安装expect工具包,比如用brew install expect或者apt install expect),它能模拟交互式终端环境,让程序用行缓冲而非块缓冲:
unbuffer ollama run llama3:latest | tee >(say)
方法三:用awk逐行过滤朗读(可选,避免读用户输入)
上面两种方法会把用户自己输入的内容也读出来,如果只想朗读LLM的回复,可以用awk过滤特定前缀(比如LLM回复开头的llama: ),只处理对应的内容:
ollama run llama3:latest | tee >(awk '/^llama: / {sub(/^llama: /, ""); system("say " $0)}')
这里/^llama: /匹配以llama: 开头的行,sub(/^llama: /, "")去掉前缀,然后用system("say " $0)调用朗读命令,完美实现只读AI的回复。
备注:内容来源于stack exchange,提问作者yarns
相关产品推荐
相关产品推荐

