| #!/usr/bin/env python3 | |
| ''' | |
| Simple example to demonstrate using Gst.DeviceMonitor and `transcodebin` to | |
| record audio from a microphone into an .oga file | |
| ''' | |
| import gi | |
| import sys | |
| gi.require_version('Gst', '1.0') | |
| gi.require_version('GstPbutils', '1.0') | |
| gi.require_version('GLib', '2.0') | |
| gi.require_version('GObject', '2.0') | |
| from gi.repository import GLib, GObject, Gst, GstPbutils | |
| def bus_call(bus, message, loop): | |
| t = message.type | |
| Gst.debug_bin_to_dot_file_with_ts(pipeline, Gst.DebugGraphDetails.ALL, "test") | |
| if t == Gst.MessageType.EOS: | |
| sys.stdout.write("End-of-stream\n") | |
| loop.quit() | |
| elif t == Gst.MessageType.ERROR: | |
| err, debug = message.parse_error() | |
| sys.stderr.write("Error: %s: %s\n" % (err, debug)) | |
| loop.quit() | |
| return True | |
| def stop(loop, pipeline): | |
| _, position = pipeline.query_position(Gst.Format.TIME) | |
| print("Position: %s\r" % Gst.TIME_ARGS(position)) | |
| if position > 10 * Gst.SECOND: | |
| loop.quit() | |
| print("Stopping after 10 seconds") | |
| return False | |
| return True | |
| def _link_to_filesink(element, pad, filesink): | |
| if not element.link(filesink): | |
| print(f"Failed to link transcodebin to output.") | |
| sys.exit(1) | |
| if __name__ == "__main__": | |
| Gst.init(sys.argv) | |
| if len(sys.argv) != 2: | |
| print("Missing <output-location.ogg> parameter") | |
| sys.exit(1) | |
| monitor = Gst.DeviceMonitor.new() | |
| monitor.add_filter("Audio/Source", None) | |
| monitor.start() | |
| # This is happening synchonously, use the GstBus based API and | |
| # monitor.start() to avoid blocking the main thread. | |
| devices = monitor.get_devices() | |
| if not devices: | |
| print("No microphone found...") | |
| sys.exit(1) | |
| default = [d for d in devices if d.get_properties().get_value("is-default") is True] | |
| if len(default) == 1: | |
| device = default[0] | |
| else: | |
| print("Available microphones:") | |
| for i, d in enumerate(devices): | |
| print("%d - %s" % (i, d.get_display_name())) | |
| res = int(input("Select device: ")) | |
| device = devices[res] | |
| pipeline = Gst.ElementFactory.make("pipeline", None) | |
| source = device.create_element() | |
| conv = Gst.ElementFactory.make("audioconvert", None) | |
| transcodebin = Gst.ElementFactory.make("transcodebin", None) | |
| Gst.util_set_object_arg(transcodebin, "profile", "video/ogg:audio/x-opus") | |
| filesink = Gst.ElementFactory.make("filesink", None) | |
| filesink.props.location = sys.argv[1] | |
| pipeline.add(source, conv, transcodebin, filesink) | |
| source.link(conv) | |
| conv.link(transcodebin) | |
| transcodebin.connect('pad-added', _link_to_filesink, filesink) | |
| pipeline.set_state(Gst.State.PLAYING) | |
| bus = pipeline.get_bus() | |
| bus.add_signal_watch() | |
| loop = GLib.MainLoop() | |
| GLib.timeout_add_seconds(1, stop, loop, pipeline) | |
| bus.connect("message", bus_call, loop) | |
| loop.run() | |
| pipeline.set_state(Gst.State.NULL) | |
| pipeline.get_state(Gst.CLOCK_TIME_NONE) |