#### This Page

# Video Operations

- New in Lektor Version 3.2

Just like images, videos are separate files that are embedded into HTML files. Since they are media files, it's often desirable to read metadata or manipulate them in some way.

Video metadata access is powered by FFmpeg. In order to use it FFmpeg must be installed on your system and detected by Lektor. If Lektor is unable to find FFmpeg you will see the error message `Unable to locate ffmpeg or ffprobe executable. Is it installed?` in your console output if you try to use functionality that requires it.

## Accessing videos

    {% for video in this.attachments.videos %}
      <div class="video"><video src="{{ video|url }}"></div>
    {% endfor %}

Just like images you can also access them using `site.get('/myfolder').attachments.videos` or `site.get('/myfolder').attachments.get('examplevideo.mp4')`. Note that not all formats are detected as videos (see attachments). If your format is not in the list you may still be able to get it detected as a video by adding it to your Lektor project file.

## Accessing metadata

Video objects are sub-classes of Attachments but with a few extra properties.

Attribute | Description
--- | ---
`width` | Video height in pixels
`height` | Video height in pixels
`duration` | Video length as a `datetime.timedelta` instance

Example:

    {% set video = this.attachments.videos.first() %}
    <video src="{{ video|url }}">
    <dl>
      <dt>Width:</dt>
      <dd>{{ video.width }} px</dd>
      <dt>Height:</dt>
      <dd>{{ video.height }} px</dd>
      <dt>Duration:</dt>
      <dd>{{ video.duration.total_seconds() }} s</dd>
    </dl>

## Generating thumbnails

The main difference between video and image attachments is how thumbnails are handled. Since a video basically is a long sequence of images you must first choose where in the video the thumbnail should be generated. This is done using the `.frame() method. There are multiple ways of calling it:

Method | Description
--- | ---
`frame()` | Use a frame from the middle of the video (default)
`frame(seek: float)` | Fraction between 0.0 and 1.0 of the video duration from where to extract the frame. The value `0.5` means that the middle of the video will be used. It can be seen as a shorthand for `video.frame(video.duration * seek)`.
`frame(seek: datetime.timedelta)` | Use a frame at the given seek distance from the beginning of the video. This is useful when you want to seek a fix time into a video.

Calling this method will return a `VideoFrame` instance, which is not usable by itself. It does however just like an image have a thumbnail method.

Example:

    {% set video = this.attachments.videos.first() %}
    <img src="{{ video.frame().thumbnail(300, 200, mode="crop")|url }}">
    <img src="{{ video.frame(0.1).thumbnail(300, 200, mode="crop")|url }}">

Note that unlike images it is not possible to get an URL to a video frame directly:

    {% set video = this.attachments.videos.first() %}
    <img src="{{ video.frame()|url }}"> <!-- This is not valid -->

## Comments