如何在Golang中使用gobuffalo/packr

4
我正在尝试在Golang中播放.wav文件的声音,并希望使用packr将.wav文件打包到可执行文件中。
我已经创建了一个非常小的项目packr-test repository,其中包含代码。
当我在默认文件夹中运行可执行文件(./packr-test)时,声音会播放。但是,当我将可执行文件移动到另一个目录时,尝试播放声音文件时出现错误。我认为这可能意味着声音文件没有与可执行文件捆绑在一起。
这是在Ubuntu上。我正在使用“play”命令,该命令通常是默认安装的,但如果不存在,则可以通过以下方式完成:
sudo apt-get install sox
sudo apt-get install sox libsox-fmt-all

使用play命令:
play file_name.extension

为了节省您查找的时间,这是我的Go代码:
package main

import (
    "fmt"
    "os/exec"

    "github.com/gobuffalo/packr"
)

func main() {

    soundsBox := packr.NewBox("./sounds")
    if soundsBox.Has("IEEE_float_mono_32kHz.wav") {
        fmt.Println("It's there.")
    } else {
        fmt.Println("It's not there.")
    }

    args := []string{"-v20", "./sounds/IEEE_float_mono_32kHz.wav"}
    output, err := exec.Command("play", args...).Output()
    if err != nil {
        // Play command was not successful
        fmt.Println("Got an error.")
        fmt.Println(err.Error())
    } else {
        fmt.Println(string(output))
    }

}

这是我的输出:
sudo ./packr-test 
It's there.
Got an error.
exit status 2
1个回答

5

即使您已将文件打包到二进制文件中,仍然在引用文件系统上的文件:

args := []string{"-v20", "./sounds/IEEE_float_mono_32kHz.wav"}
output, err := exec.Command("play", args...).Output()

您可以通过以下方式从您的packr盒中获取文件数据:
bytes, err := soundsBox.FindBytes("IEEE_float_mono_32kHz.wav")

为了使用exec.Command()执行文件,我认为你需要将这些字节写回文件系统:
err := ioutil.WriteFile("/tmp/IEEE_float_mono_32kHz.wav", bytes, 0755)
exec.Command("play", []string{"-v20", "/tmp/IEEE_float_mono_32kHz.wav"}

你也许可以通过标准输入将你的字节传递给play,但这将取决于play二进制文件的工作方式。

cmd.Stdin = bytes
cmd.Run()

嗯,这看起来没问题。但是,那么用packr打包的每个资源都不会遇到同样的问题吗?比如说你打包了一些HTML文件,然后提供服务,为什么它们不需要被重新写回文件系统呢? - davo36
1
这取决于您如何使用文件数据。我经常使用packr来嵌入诸如SQL查询、HTML模板、图像、字体等内容,但我会从packr盒子中读取字节,然后直接将这些字节传递给接受[]byte参数的函数。您正在调用操作系统调用的exec,因此您必须以与在命令行上调用play相同的方式传递声音文件(即作为文件系统路径)。 - Matt
是的,我明白你的意思。我想你可能是对的。糟糕了。这意味着我们最好将声音文件与可执行文件一起分发。要么这样,要么尝试找到一些不需要调用exec的播放文件的方法... - davo36
我快速查看了一些Go语言音频库,有几个可用,但我不确定它们的易用性如何。例如,这里有一个mp3库 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接