GStreamer appsink 比 filesink 慢得多

GStreamer appsink is much more slower than filesink

我正在尝试使用 golang 中的 GStreamer 将 MP3 文件转换为 wave。这是 createPipeline() 函数:

func createPipeline() (*gst.Pipeline, error) {
    gst.Init(nil)

    // Create a pipeline
    pipeline, err := gst.NewPipelineFromString(
        "appsrc name=src ! decodebin ! audioresample ! audioconvert ! audio/x-raw,format=S16LE,rate=16000 ! wavenc ! appsink name=sink")

    if err != nil {
        return nil, err
    }

    srcElem, err := pipeline.GetElementByName("src")

    if err != nil {
        return nil, err
    }
    src := app.SrcFromElement(srcElem)
    src.SetCallbacks(&app.SourceCallbacks{
        NeedDataFunc: func(self *app.Source, _ uint) {

            // If we've reached the end of the palette, end the stream.
            bytes, _ := os.ReadFile("/tmp/a.mp3")
            buffer := gst.NewBufferFromBytes(bytes)
            self.PushBuffer(buffer)
            src.EndStream()
        },
    })

    sinkElem, err := pipeline.GetElementByName("sink")

    if err != nil {
        return nil, err
    }
    sink := app.SinkFromElement(sinkElem)
    sink.SetCallbacks(&app.SinkCallbacks{
        // Add a "new-sample" callback
        NewSampleFunc: func(sink *app.Sink) gst.FlowReturn {

            // Pull the sample that triggered this callback
            sample := sink.PullSample()
            if sample == nil {
                return gst.FlowEOS
            }

            os.WriteFile("a.wav", sample.GetBuffer().Bytes(), 0644)

            return gst.FlowOK
        },
    })

    return pipeline, nil
}

我有两个选择。第一个是使用 filesink 元素将结果保存到文件中,第二个是使用 appsink 元素并获取样本并写入文件。我认为这两种方法的性能应该几乎相同。但是当我使用 appsink 时,它比 filesink 花费了更多的时间。我正在使用 GStreamer 的 this binding for go。

您可以尝试延迟跟踪器来检查管道元素之间的延迟。如果两个pipeline都一样,可能是磁盘io的问题,可以通过写入磁盘前缓冲来解决。

请注意,appsink 默认与时钟同步,而 filesink 不同步。因此,当您使用 appsink 时,缓冲区将与管道时钟同步 - 这将使您的管道 运行 实时(而不是更快)。将你的 appsink 的 sync 属性 设置为 false: .. ! appsink name=sink sync=false.