Try it out: https://media-viewer.netlify.app/
Source code: https://github.com/mornir/media-viewer-ts
Introduction
I was unhappy with the media viewer applications available on Windows. After searching for a few hours, I couldn't find any program that fulfilled my short list of requirements:
- Reads both images and videos
- Navigates between media with keyboard or mouse wheel
- Autoplays video, preferably in a loop
- Works locally (direct read from the disk, no upload to server)
So I thought I could just code my own application.
Electron or not?
I'm a front-end developer, which limits my possibilities. Since I needed read access to the disk, my first thought was to use Electron. I've never worked with Electron before and actually I've been avoiding it so far. My guess is that PWA or another tech is going to replace it in the short to medium term. So I was not too eager to learn how to build apps with Electron in 2021.
While doing some research about Electron, I came across this Electron application. It was exactly what I needed, except that it couldn't read videos.😫
However, the same author also published a great npm package which had more capabilities, among other reading video files.🥳
Remembering hearing about the new File Access API, I told myself why not just build a website?
webkitdirectory vs File Access API
At first I thought that using the File Access API was the only way to read the content of a folder. But actually the webkitdirectory attribute on the <input type="file">
element allows just that! So a basic input
tag with the webkitdirectory
attribute is exactly what I needed.
I think that the File Access API is more for advanced usages, like letting users save changes directly back to the disk (see for example this text editor demo)
createObjectURL
Media files are to be read locally, directly from the disk. But I still needed some sort of URL for the src
attributes of img
and video
tags. First I thought about converting images to base64, but this is a expensive process and it doesn't work for videos. Like stated in this post, the right way is with URL.createObjectURL. This method creates a temporary local URL that can be used by the src
attribute.
The lifespan of the URL is bound to the HTML document. When the tab is closed, the URL is removed from memory. However it's best practice to free up memory as soon as the URL is no longer needed, using the URL.revokeObjectURL method and passing it the blob URL. In my case, I call it once images and videos have loaded or when the gallery is closed.
Vite & Typescript
I've always used Vite exclusively for Vue 3 projects, and I was pleasantly surprised to see that it works also great for "pure" TypeScript (vanilla-ts
Vite template). From now on, I will use Vite for all my front-end projects, even when I'm not using Vue.
Try it out: https://media-viewer.netlify.app/
Source code: https://github.com/mornir/media-viewer-ts