Embedding videos in Jekyll

Screenshot from 2017-04-25 04-38-02

One of the main reasons I went with a markdown -> pandoc portfolio site instead of using jekyll: I couldn’t figure out how to embed “local” videos (video files inside my site, not from youtube or vimeo) in the jekyll sites.

Screenshot from 2017-04-25 04-44-42

Previously I was using the Jekyll Freelancer theme. With some modifications to allow for arrow key navigation.


However, any file that had a youtube video, I had to drop down to raw HTML. This was pretty painful. And since I was coercing the posts format to deal with “projects”, I had a crazy directory structure, something like “2015-01-01-project1.html”, which made editing lots of projects at once really annoying.

Thus, recently I switched to making my portfolio/project site in Markdown.
This was still kind of painful, but gave me a lot more control over the look.
I also enjoyed the minimalist structure of the final site, as compared to the glossy-yet-not-super-functional previous look when I built my site on top of the jekyll freelancer theme.

With my new webdev experience from bashing at grav for days on end, I was pretty easily able to modify this youtube embed script to do what I wanted.

I still find the post-first nature of jekyll annoying, yet it seems very reasonable to me now that I can just ignore that functionality entirely and build the rest of the site taking advantage of the templating engine and data / yaml features. After bashing at Grav, I’m also a lot more comfortable writing my own “page templates” for iterating through data files.

That is, I now understand how to leave the posts folder blank (ignore it entirely) and just write pages using my own Liquid templates.

Tutorial here: https://jekyllrb.com/tutorials/navigation/

Before, the Jekyll structure seemed overwhelming, at as always I’m only updating/creating a portfolio site when I’m applying to something. So I would always get frustrated and give up halfway through when creating/updating the portfolio site would take at least two entire days away from applications.

I also just tried and really enjoy the jekyll admin plugin, which allows me to upload files (via drag-and-drop) and provides a convenient browser-based GUI for creating pages.

The markdown file format I ended up settling down on started getting tedious and hard to organize as well. There was a lot of repetition that Liquid templating would solve. And a lot of “magic filenames” that were not human-readable, and annoying to keep consistent.

Screenshot from 2017-04-25 04-49-45

So it may be time to redo my portfolio site again.

Grav is more powerful, but even more “jargon heavy” / heavier of a web framework. You can do fancy things such as user authentication etc. in Grav. But dangnggg it is a heavy framework with a really complex file structure that appears like magical voodoo that is impossible to understad to newcomers…

For a sample of the craziness, see: https://github.com/nouyang/grav-plugin-milestones


On to the actual video-embedding plugin. The key was figuring out how to access the Jekyll site variables from within the plugin file. Turns out you use the syntax Jekyll.configuration({})['url' (and use “||” to provide a default value).


1. https://jekyllrb.com/docs/quickstart/
2. Create a file, “my_site/_plugins
(create the _plugins folder if it doesn’t exist yet in your jekyll install)
3. Create a file called “video.rb” (or whatever you want) with the code at the bottom of this page
4. Put a video file in your site. Usually you can create an “assets” or “downloads” folder. For instance, I put a “spacetestSMALL_512kb.mp4” file into “my_site/assets” folder
Note: mp4 works consistently in all my browsers. ogv did not.
4. Use in your posts with following format:
{% Video spacetestSMALL_512kb.mp4 500 400 %}


class Video < Liquid::Tag
  Syntax = /^\s*([^\s]+)(\s+(\d+)\s+(\d+)\s*)?/

  def initialize(tagName, markup, tokens)

    @url = Jekyll.configuration({})['url'] || 'http://example.com'

    if markup =~ Syntax then
      @id = $1

      if $2.nil? then
          @width = 560
          @height = 420
          @width = $2.to_i
          @height = $3.to_i
      raise "No Video Source provided"


  def lookup(context, name)
    lookup = context
    name.split(".").each { |value| lookup = lookup[value] }

  def render(context)
     "<iframe width=\"#{@width}\" height=\"#{@height}\" src=\"#{@base_url}/#{@id}\" ></iframe>"

  Liquid::Template.register_tag "Video", self



Screenshot from 2017-04-25 04-38-02

One thought on “Embedding videos in Jekyll”

  1. Thanks for your post.

    It seems that the Regexp is wrong because $2 catchs the width + the height and $3 the width.

    So I change
    width= $3
    height = $4

    I will be better to fix the regexp.

Comments are closed.