-
-
Save dplanella/5563018 to your computer and use it in GitHub Desktop.
# Video thumbnailer, non-PyGI version, working as expected | |
import os | |
import sys | |
import gst | |
def get_frame(path, offset=5, caps=gst.Caps('image/png')): | |
pipeline = gst.parse_launch('playbin2') | |
pipeline.props.uri = 'file://' + os.path.abspath(path) | |
pipeline.props.audio_sink = gst.element_factory_make('fakesink') | |
pipeline.props.video_sink = gst.element_factory_make('fakesink') | |
pipeline.set_state(gst.STATE_PAUSED) | |
# Wait for state change to finish. | |
pipeline.get_state() | |
assert pipeline.seek_simple( | |
gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH, offset * gst.SECOND) | |
# Wait for seek to finish. | |
pipeline.get_state() | |
buffer = pipeline.emit('convert-frame', caps) | |
pipeline.set_state(gst.STATE_NULL) | |
return buffer | |
def main(): | |
buf = get_frame(sys.argv[1]) | |
with file('frame.png', 'w') as fh: | |
fh.write(bytes(buf)) | |
if __name__ == '__main__': | |
main() |
# Video thumbnailer, PyGI version, not working (creates unreadable thumbnails) | |
import os | |
import sys | |
import gi | |
gi.require_version('Gst', '1.0') | |
from gi.repository import GObject, Gst | |
Gst.init(None) | |
def get_frame(path, offset=5, caps=Gst.Caps.from_string('image/png')): | |
pipeline = Gst.parse_launch('playbin') | |
pipeline.props.uri = 'file://' + os.path.abspath(path) | |
pipeline.props.audio_sink = Gst.ElementFactory.make('fakesink', 'fakeaudio') | |
pipeline.props.video_sink = Gst.ElementFactory.make('fakesink', 'fakevideo') | |
pipeline.set_state(Gst.State.PAUSED) | |
# Wait for state change to finish. | |
pipeline.get_state(Gst.CLOCK_TIME_NONE) | |
assert pipeline.seek_simple( | |
Gst.Format.TIME, Gst.SeekFlags.FLUSH, offset * Gst.SECOND) | |
# Wait for seek to finish. | |
pipeline.get_state(Gst.CLOCK_TIME_NONE) | |
buffer = pipeline.emit('convert-sample', caps).get_buffer() | |
pipeline.set_state(Gst.State.NULL) | |
return buffer | |
def main(): | |
buf = get_frame(sys.argv[1]) | |
with file('frame.png', 'w') as fh: | |
# This (i.e. getting the data from the buffer) does not work. See https://bugzilla.gnome.org/show_bug.cgi?id=678663 | |
fh.write(bytes(buf)) | |
if __name__ == '__main__': | |
main() |
You're right, I don't need a 1 second timeout, I was just adding an arbitrary value to get the rest of the snippet working. Thanks a lot for the Gst.CLOCK_TIME_NONE
tip, I've now added that.
Do you know if any progress was made on this, a friend and I are working on a project, https://github.com/mateosalta/CamCastic-Desktop , and are planning to grab an image to measure the proper proportions/resolution of the camera, then use that to provide a "black bar" free window. This snippet seems like a step in the right direction. (using pygi)
Nevermind on the getting resolution that way... I found a better way to do it. Alternately, I'm still playing with the thumbnailer snippet if you want something that works.
The code above isn't working in my environment. I solved it by doing the following:
Replace:
buffer = pipeline.emit('convert-sample', caps).get_buffer()
with
sample = pipeline.emit('convert-sample', caps)
buffer = sample.get_buffer()
Also replace: with file('frame.png', 'w') as fh:
with with file('frame.png', 'wb') as fh:
As stated bytes(buf) doesn't work, so you will have to do it another way:
with file('frame.png', 'w') as fh:
fh.write(buf.extract_dup(0, buf.get_size()))
Also as wongcc966422 said, you will need 'wb' file mode on Windows. It works with 'w' on Linux for me.
This seems to have broken in a recent version of gstreamer?
I can't get it work with mp4 file which is h264 (High profile) / AAC. But this works with webm file.
convert-sample returns None in mp4's case.
Do you actually want a 1 second timeout on the state change and seek? If you do, you probably want to check the return value of get_state(). Otherwise, you probably want Gst.CLOCK_TIME_NONE.