使用GStreamer的gnonlin进行速度变化

时间:2014-04-23 09:12:09

标签: python gstreamer gnonlin

我的目标是一起编辑不同音频文件的部分,并将这些部分中的每一部分应用于单个时间拉伸效果(Pitch元素的速度属性)。每个段在最终混音中应持续12秒,因此输出文件长度为36秒。以下代码对3个文件执行此操作(可以通过使用循环并将所有内容存储到列表中进行扩展)。 [是的,它有点长]

import gst, gobject
gobject.threads_init()
import numpy as np
import math

comp  = gst.element_factory_make("gnlcomposition", "composition")

gsrc1 = gst.element_factory_make("gnlfilesource")
gsrc1.props.location = "file1.mp3"
gsrc1.props.start          = 0
gsrc1.props.duration       = ?
gsrc1.props.media_start    = 0
gsrc1.props.priority       = 3
comp.add(gsrc1)

gsrc2 = gst.element_factory_make("gnlfilesource")
gsrc2.props.location = "file2.mp3"
gsrc2.props.start          = ?
gsrc2.props.duration       = ?
gsrc2.props.media_start    = 0
gsrc2.props.priority       = 4
comp.add(gsrc2)

gsrc3 = gst.element_factory_make("gnlfilesource")
gsrc3.props.location = "file3.mp3"
gsrc3.props.start          = ?
gsrc3.props.duration       = ?
gsrc3.props.media_start    = 0
gsrc3.props.priority       = 5
comp.add(gsrc3)

bin = gst.Bin()
audioconvertbin = gst.element_factory_make("audioconvert")
pitch1 = gst.element_factory_make("pitch")
pitch1.set_property("tempo", 1.05)
bin.add(audioconvertbin, pitch1)
audioconvertbin.link(pitch1)
bin.add_pad(gst.GhostPad("sink", audioconvertbin.get_pad("sink")))
bin.add_pad(gst.GhostPad("src", pitch1.get_pad("src")))

bin2 = gst.Bin()
audioconvertbin2 = gst.element_factory_make("audioconvert")
pitch2 = gst.element_factory_make("pitch")
pitch2.set_property("tempo", 0.95)
bin2.add(audioconvertbin2, pitch2)
audioconvertbin2.link(pitch2)
bin2.add_pad(gst.GhostPad("sink", audioconvertbin2.get_pad("sink")))
bin2.add_pad(gst.GhostPad("src", pitch2.get_pad("src")))

bin3 = gst.Bin()
audioconvertbin3 = gst.element_factory_make("audioconvert")
pitch3 = gst.element_factory_make("pitch")
pitch3.set_property("tempo", 1.1)
bin3.add(audioconvertbin3, pitch3)
audioconvertbin3.link(pitch3)
bin3.add_pad(gst.GhostPad("sink", audioconvertbin3.get_pad("sink")))
bin3.add_pad(gst.GhostPad("src", pitch3.get_pad("src")))

op = gst.element_factory_make("gnloperation")
comp.add(op)

op2 = gst.element_factory_make("gnloperation", "op2")
comp.add(op2)

op3 = gst.element_factory_make("gnloperation", "op3")
comp.add(op3)

op.add(bin)
op.props.start          = 0 * gst.SECOND
op.props.duration       = ?
op.props.priority       = 1
op2.add(bin2)
op2.props.start          = ?
op2.props.duration       = ?
op2.props.priority       = 1
op3.add(bin3)
op3.props.start          = ?
op3.props.duration       = ?
op3.props.priority       = 1

pipeline = gst.Pipeline()
audioconvert = gst.element_factory_make("audioconvert")
encoder = gst.element_factory_make("vorbisenc")
mux = gst.element_factory_make("oggmux")
filesink = gst.element_factory_make("filesink")
filesink.set_property("location", "output.ogg")
pipeline.add(comp, audioconvert, encoder, mux, filesink)
gst.element_link_many(audioconvert, encoder, mux, filesink)

def on_pad(comp, pad, elements):
    convpad = elements.get_compatible_pad(pad, pad.get_caps())
    pad.link(convpad)
comp.connect("pad-added", on_pad, audioconvert)

loop = gobject.MainLoop(is_running=True)
bus = pipeline.get_bus()
bus.add_signal_watch()
def on_message(bus, message, loop):
    if message.type == gst.MESSAGE_EOS:
        loop.quit()
    elif message.type == gst.MESSAGE_ERROR:
        print message
        loop.quit()
bus.connect("message", on_message, loop)
pipeline.set_state(gst.STATE_PLAYING)
loop.run()
pipeline.set_state(gst.STATE_NULL)

1 个答案:

答案 0 :(得分:0)

我发现“?”的“最佳”值是:

gsrc1 = gst.element_factory_make("gnlfilesource")
gsrc1.props.location = "file1"
gsrc1.props.start          = 0
gsrc1.props.duration       = 12 * 1.05 * gst.SECOND
gsrc1.props.media_start    = 0
gsrc1.props.priority       = 3
comp.add(gsrc1)

gsrc2 = gst.element_factory_make("gnlfilesource")
gsrc2.props.location = "file2.mp3"
gsrc2.props.start          = int(12 * 1.05 * gst.SECOND)
gsrc2.props.duration       = int(12 * gst.SECOND)
gsrc2.props.media_start    = 36 * gst.SECOND
gsrc2.props.priority       = 4
comp.add(gsrc2)

gsrc3 = gst.element_factory_make("gnlfilesource")
gsrc3.props.location = "file3.mp3"
gsrc3.props.start          = int(12 * 1.05 * gst.SECOND + 12 * gst.SECOND)
gsrc3.props.duration       = int(12 * 1.1 * gst.SECOND)
gsrc3.props.media_start    = 60 * gst.SECOND
gsrc3.props.priority       = 4
comp.add(gsrc3)

op.add(bin)
op.props.start          = 0 * gst.SECOND
op.props.duration       = int(12 * 1.05 * gst.SECOND)
op.props.priority       = 1

op2.add(bin2)
op2.props.start          = int(12 * 1.05 * gst.SECOND)
op2.props.duration       = int(12 * gst.SECOND)
op2.props.priority       = 1

op3.add(bin3)
op3.props.start          = int(12 * 1.05 * gst.SECOND + 12 * gst.SECOND)
op3.props.duration       = int(12 * 1.1 * gst.SECOND)
op3.props.priority       = 1

简而言之,你不应该考虑速度变化< 1有任何后果,但你应该考虑速度变化> 1(从用户的角度来看,这是一种奇怪的行为)。

我将它与Audacity进行了比较,它给出了大致相同的结果,除了两个粗略的0.026s摘录之间存在细微的差距。我不认为这是由于舍入错误,也许我的持续时间/开始时间设置不正确(请参见下图中的间隙)。

Gap between excerpts

希望它会帮助一些人。