我尝试在golang中使用os/exec调用shell命令,该命令将花费一些时间,因此我希望检索retime输出并打印处理后的输出(一个进度比率数字)。
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"strings"
)
func main() {
cmdName := "ffmpeg -i t.webm -acodec aac -vcodec libx264 cmd1.mp4"
cmdArgs := strings.Fields(cmdName)
cmd := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
stdout, _ := cmd.StdoutPipe()
cmd.Start()
go print(stdout)
cmd.Wait()
}
// to print the processed information when stdout gets a new line
func print(stdout io.ReadCloser) {
r := bufio.NewReader(stdout)
line, _, err := r.ReadLine()
fmt.Println("line: %s err %s", line, err)
}
我想有一个功能,可以更新屏幕时,命令打印的东西,
ffmpeg命令输出如下:
frame= 101 fps=0.0 q=28.0 size= 91kB time=00:00:04.13 bitrate= 181.2kbits/
frame= 169 fps=168 q=28.0 size= 227kB time=00:00:06.82 bitrate= 272.6kbits/
frame= 231 fps=153 q=28.0 size= 348kB time=00:00:09.31 bitrate= 306.3kbits/
frame= 282 fps=140 q=28.0 size= 499kB time=00:00:11.33 bitrate= 360.8kbits/
事实上,上面的4行是ffmpeg命令输出的最后一行,它一直在变化,我想打印出变化,就像
18%
44%
69%
100%
我怎样才能做到这一点?
5条答案
按热度按时间eanckbw91#
看起来ffmpeg将所有的诊断信息(“控制台输出”)发送到stderr而不是stdout。下面的代码对我很有效。
ffmpeg的版本如下。
os8fio9y2#
我确实发现他在那篇文章中提到的icza的解决方案非常有用,但是它并没有解决我的问题。
我做了一个小测试如下:
1、我写了一个脚本,每秒钟打印一个信息十次,这里是script.sh
2、读取stdout并从stdout中提取所需的信息并做一些处理以得到预期的格式,下面是代码: Package 主体
这对于我的www.example.com测试是有效script.sh的,但是对于ffmpeg命令它不起作用,在ffmpeg的情况下,没有打印任何内容,过程完成(没有停滞),我猜ffmpeg将数据写入stdout的方式有点特殊(可能根本没有换行符,我尝试了icza的解决方案,但是它仍然不起作用)。
8dtrkrch3#
检查下面,需要增强(不建议使用,因为它是),但工作:)
xxhby3vn4#
当你有一个从Go语言中启动的外部命令的
exec.Cmd
值时,你可以使用它的Cmd.Stdin
、Cmd.Stdout
和Cmd.Stderr
字段以某种方式与进程通信。重点是 * 标准 *。如果外部进程正在通过网络连接发送数据,或者正在将数据写入文件,您将无法通过上述3个流拦截这些数据。
ffmpeg
、ffmpeg
和许多其他控制台应用程序并不向标准输出/错误写入数据,但它们使用系统调用或其他库(使用系统调用)来操作终端窗口。当然,应用程序可以向标准输出/错误发送 * 一些 * 数据,并可以通过操作终端窗口来显示 * 其他 * 数据。因此,您看不到
ffmpeg
的输出,因为您试图读取其标准输出/error,但ffmpeg
不会通过写入这些流来显示其输出。在一般情况下,如果你想捕获这类应用程序的输出,你需要一个能够捕获终端窗口(文本)内容的库。在更简单的情况下,应用程序支持将这些输出转储到文件中,通常由额外的命令行参数控制,然后你可以从Go语言中读取/监视这些文件。
ecbunoof5#
**cmd.StderrPipe()**将不起作用,请改用cmd.StdoutPipe():