| #!/usr/bin/env python | |
| # gst-python | |
| # Copyright (C) 2006 Andy Wingo <wingo at pobox.com> | |
| # Copyright (C) 2023 Jan Schmidt <jan at centricular.com> | |
| # | |
| # This library is free software; you can redistribute it and/or | |
| # modify it under the terms of the GNU Library General Public | |
| # License as published by the Free Software Foundation; either | |
| # version 2 of the License, or (at your option) any later version. | |
| # | |
| # This library is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| # Library General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU Library General Public | |
| # License along with this library; if not, write to the | |
| # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
| # Boston, MA 02110-1301, USA. | |
| import os | |
| import sys | |
| import gi | |
| gi.require_version("GLib", "2.0") | |
| gi.require_version("Gst", "1.0") | |
| gi.require_version("GstPbutils", "1.0") | |
| from gi.repository import GLib, Gst, GstPbutils | |
| def fail(path, info): | |
| error = info.get_result() | |
| print(f"Discovery of {path} failed with result {error}") | |
| sys.exit(1) | |
| def print_stream_info(stream_info, depth): | |
| indent = " "*depth | |
| stream_type = stream_info.get_stream_type_nick() | |
| stream_num = stream_info.get_stream_number() | |
| stream_id = stream_info.get_stream_id() | |
| caps = stream_info.get_caps() | |
| print(f"{indent}{stream_type} #{stream_num}: {caps}") | |
| print(f"{indent} Stream ID: {stream_id}") | |
| tags = stream_info.get_tags() | |
| if tags is not None: | |
| print(f"{indent} Tags: ") | |
| for (key, tag) in tags.enumerate(): | |
| print(f"{indent} {key}: {tag}") | |
| if isinstance(stream_info, GstPbutils.DiscovererVideoInfo) or isinstance(stream_info, GstPbutils.DiscovererAudioInfo): | |
| print(f"{indent}Bitrate: {stream_info.get_bitrate()}") | |
| print(f"{indent}Max Bitrate: {stream_info.get_max_bitrate()}") | |
| print() | |
| def print_topology(stream_info, depth): | |
| print_stream_info(stream_info, depth) | |
| next = stream_info.get_next() | |
| if next is not None: | |
| print_topology (next, depth + 2); | |
| elif isinstance(stream_info, GstPbutils.DiscovererContainerInfo): | |
| streams = stream_info.get_streams() | |
| for tmpinf in streams: | |
| print_topology (tmpinf, depth + 2); | |
| def succeed(info): | |
| print(f"URI: {info.get_uri()}") | |
| # Print properties | |
| duration = info.get_duration() | |
| seekable = info.get_seekable() | |
| is_live = info.get_live() | |
| print(f"Duration: {Gst.TIME_ARGS(duration)}\nSeekable: {seekable}\nLive: {is_live}") | |
| print_topology(info.get_stream_info(), 0) | |
| sys.exit(0) | |
| def discover(path): | |
| def discovered(d, info, err): | |
| if info.get_result() == GstPbutils.DiscovererResult.OK: | |
| succeed(info) | |
| else: | |
| fail(path, info) | |
| d = GstPbutils.Discoverer.new(5 * Gst.SECOND) | |
| d.connect('discovered', discovered) | |
| d.start() | |
| d.discover_uri_async(path) | |
| GLib.MainLoop().run() | |
| def usage(): | |
| print("usage: gst-discover PATH-TO-MEDIA-FILE", file=sys.stderr) | |
| sys.exit(1) | |
| def main(argv): | |
| if len(argv) != 2: | |
| usage() | |
| path = argv.pop() | |
| if not os.path.isfile(path): | |
| print(f"error: file {path} does not exist", file=sys.stderr) | |
| usage() | |
| Gst.init(sys.argv) | |
| return discover('file://' + os.path.abspath(path)) | |
| if __name__ == '__main__': | |
| sys.exit(main(sys.argv)) |