Implementing .Width and .Height for video resources

Hello everyone!

I think like probably many are already doing, I have images in my site that I need to dynamically resize through CSS. I also use lazy loading so that makes it a bit hard for browsers to know how many pixels they need to allocate in the page so the layout doesn’t shift later on when scrolling and loading the page.

This can automatically be solved by slightly editing the figure shortcode and getting the .Width and .Height from a local image if values are not provided.

However, the same is not yet possible for videos, as the Width and Height methods are simply not implemented.

I know, and this is what I have done so far, that I can manually set the correct width and height by passing it as a parameter. But if possible, I’d like to contribute this functionality so it’s available out of the box.

Now, I recognise video is a complex topic, with many different formats, and I’m also not a Golang developer at the day job. So I would propose keeping it small, just the Width and Height methods working for now (Resizing and other more complex ones might be best left to full tools such as ffmpeg or video editors); and if adding external dependencies is not an option, I’d also just start with one or a very limited number of formats, such as WEBM. If adding new dependencies is an option, I’m sure there are already Golang packages to read video metadata of many different formats.

Thanks for reading and hope you have a great day!

This is unlikely to happen without a native Go package, and the creation of a native Go package is unlike to happen either.

Use a bash script before you build your site to collect the video metadata. For example, with this content structure…

content/
├── posts/
│   ├── post-1/
│   │   ├── index.md
│   │   └── video-a.mp4
│   ├── post-2/
│   │   ├── index.md
│   │   └── video-b.webm
│   └── _index.md
└── _index.md

…recursively scan the content directory for video files, then use ffprobe+jq to create a data file. Your shortcode or other template can then lookup the entry in the data file to get width, height, duration, etc.

Try it:

git clone --single-branch -b hugo-forum-topic-56251 https://github.com/jmooring/hugo-testing hugo-forum-topic-56251
cd hugo-forum-topic-56251
./collect-video-metadata.sh
hugo server

Note that the content directory must reside on the OS file system; the content cannot be mounted from a module.

1 Like

Hey jmooring. I understand it’s not currently built-in. For now what I do is just manually run the ffprobe command myself, and just input the width and height parameters manually, pretty much the same as the shortcode/automation you just provided.

But I started this thread exactly to gauge how feasible it would be to get this added. I am far from an expert in video, Golang, or even Hugo, which I just started using around a month ago. But if it’s something the maintainers would be willing to review/accept, I’d like to try contributing it.

I don’t think I could make a comprehensive implementation for absolutely every video format out there, but I could at least contribute support for WEBM. WEBM seems to use a subset of the Matroska (MKV) specification, EBML, defined here. I think the relevant fields would be DisplayHeight and DisplayWidth (although it also contains PixelHeight and PixelWidth, I’d need to do a bit more research on the difference between the two).

If adding new dependencies is an option, I have found the following pure Go library that should be able to parse EBML to get these Height/Width fields. If adding external dependencies is a concern, I could try to write a very simple binary parser that just finds/extracts the relevant fields, again in pure Go.

I read through the Hugo README and it mentioned that people shouldn’t just provide patches, but instead go through this channel/create a feature thread, so this is why this thread.

I stand corrected on my initial search. I was focused on an exiftool equivalent and overlooked format-specific packages.

It’s true that a solution could be cobbled together using native libraries for specific video containers like MP4, WEBM, MPG, OGG, AVI, and MOV. Of these, I suspect MP4 is the most common, followed by WEBM.

With respect to including something like this in Hugo:

1) I don’t see much demand for it.

2) I am concerned about performance (speed and memory consumption). A 30-minute 1080p video is measured in GB, not MB. This may not be a problem if we don’t have to read the whole file to extract width, height, and duration (the big three).

3) I am concerned about ongoing maintenance and support (e.g., “Hey, this isn’t working with videos from my Samsung New Model phone.”). Historically, in many cases, someone contributes a feature like this, and then they aren’t around to support users or maintain the code.

4) It’s not my call.

Likewise, it’s something I was also worried about. I’d need to do more research and get a POC implementation to confirm it, but at least for WEBM and its EBML metadata format, it shouldn’t require reading the whole file, but rather just finding specific bytes within the start of the file. I suspect MP4 will be much of the same, just with a different metadata format.

I completely understand this concern. I can say I’d like to help maintain and support this functionality since I’d keep relying on it for the foreseeable future, but I obviously can’t promise that I’d be able to take a forever permanent “maintainer” role for this feature.

What I think would be a good compromise is that, if this feature gets added, I would also clearly document what the limitations are, i.e. what specific video formats are supported, as well as commands like ffprobe that can help users identify their videos, and commands that can convert to supported formats that would be supported by this implementation (ffmpeg).

Either way, I’d like to thank you for engaging with me and proposing possible workarounds. Hope you have a great Sunday :raising_hands:

1 Like