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
.
我正在尝试使用 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
.