Как создать миниатюры видео с помощью Python и Gstreamer
Я хотел бы создать миниатюры для видео MPEG-4 AVC с помощью Gstreamer и Python. По существу:
- откройте видеофайл
- искать до определенного момента времени (например, 5 секунд)
- захватить кадр в это время
- сохранить кадр на диск как .файл jpg
Я смотрел на этот и другие похожие вопросы, но я не могу понять, как сделать поиск и захват кадра автоматически без пользовательский ввод.
Итак, вкратце, как я могу захватить миниатюру видео с Gstreamer и Python в соответствии с шагами выше?
4 ответов
подробнее о энсоникответ, Вот пример:
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(str(buf))
if __name__ == '__main__':
main()
это создает PNG-изображение. Вы можете получить необработанные данные изображения, используя gst.Caps("video/x-raw-rgb,bpp=24,depth=24")
или что-то подобное.
обратите внимание, что в GStreamer 1.0 (в отличие от 0.10), playbin2
переименовано в playbin
и convert-frame
сигнал называется convert-sample
.
механика поиска объясняется в эта глава руководства по разработке приложений GStreamer. В 0.10 playbin2
документация больше не кажется онлайн, но документация для 1.0 является здесь.
пример в Vala, с GStreamer 1.0 :
var playbin = Gst.ElementFactory.make ("playbin", null);
playbin.set ("uri", "file:///path/to/file");
// some code here.
var caps = Gst.Caps.from_string("image/png");
Gst.Sample sample;
Signal.emit_by_name(playbin, "convert-sample", caps, out sample);
if(sample == null)
return;
var sample_caps = sample.get_caps ();
if(sample_caps == null)
return;
unowned Gst.Structure structure = sample_caps.get_structure(0);
int width = (int)structure.get_value ("width");
int height = (int)structure.get_value ("height");
var memory = sample.get_buffer().get_memory (0);
Gst.MapInfo info;
memory.map (out info, Gst.MapFlags.READ);
uint8[] data = info.data;
используйте playbin2. установите uri в медиафайл, используйте gst_element_seek_simple для поиска нужной временной позиции, а затем используйте g_signal_emit для вызова сигнала действия "convert-frame".
Это старый вопрос, но я до сих пор не нашел его нигде.
Я обнаружил, что следующее работает над воспроизведением видео с Gstreamer 1.0
import gi
import time
gi.require_version('Gst', '1.0')
from gi.repository import Gst
def get_frame():
caps = Gst.Caps('image/png')
pipeline = Gst.ElementFactory.make("playbin", "playbin")
pipeline.set_property('uri','file:///home/rolf/GWPE.mp4')
pipeline.set_state(Gst.State.PLAYING)
#Allow time for it to start
time.sleep(0.5)
# jump 30 seconds
seek_time = 30 * Gst.SECOND
pipeline.seek(1.0, Gst.Format.TIME,(Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE),Gst.SeekType.SET, seek_time , Gst.SeekType.NONE, -1)
#Allow video to run to prove it's working, then take snapshot
time.sleep(1)
buffer = pipeline.emit('convert-sample', caps)
buff = buffer.get_buffer()
result, map = buff.map(Gst.MapFlags.READ)
if result:
data = map.data
pipeline.set_state(Gst.State.NULL)
return data
else:
return
if __name__ == '__main__':
Gst.init(None)
image = get_frame()
with open('frame.png', 'wb') as snapshot:
snapshot.write(image)
код должен работать как с Python2, так и с Python3, я надеюсь, что это кому-то поможет.