DEC
5
2025

Creating videos for your page can be tricky, especially if you ensure your videos load quickly, play smoothly, auto start, and work across all devices and browsers.

Here are my essential snippets I've kept to myself for far too long!

Prerequisites

Before we dive in you'll need ffmpeg installed. Use whatever package manager your system has to install it (Chocolatey or winget on Windows, apt or pacman on Linux, HomeBrew or MacPorts on macOS).

An optimized MP4 with maximum compatibility

Here's the command I use to create an MP4 optimized for web playback with broad compatibility and quick starts:

ffmpeg -i input.mov -filter:v "scale=960:540,crop=360:540" -c:v libx264 -crf 23 -profile:v baseline -level 3.0 -pix_fmt yuv420p -c:a aac -an -ss 2 -t 5 -movflags faststart output.mp4
Explain the options

Let's break down each switch and when you might want to change it:

  • -i input.mov: Specifies the input file. Replace this with the name of your source video file. You want high resolution, low compression source material.
  • -filter:v "scale=960:540,crop=360:540": Applies video filters. This scales the video to 960x540, then crops it to 360x540 (a 2:3 aspect ratio).
    • Adjust scale=960:540 to your target dimensions. Use -1 to maintain aspect ratio: scale=960:-1 scales width and calculates height automatically.
    • The optional ,crop=360:540 crops to the final size. Adjust based on your design requirements. You can also crop from a specific position: crop=360:540:100:50 (width:height❌y).
  • -c:v libx264: Sets the video codec to H.264 (libx264 encoder). This is the most compatible codec for web video.
  • -crf 23: Constant Rate Factor controls quality vs file size. Lower values = higher quality but larger files. Range is 0-51, where:
    • 18-23 is visually lossless to high quality (recommended for web)
    • 23-28 is good quality (good balance)
    • 28+ is lower quality but smallest files
  • -profile:v baseline: Sets the H.264 profile to baseline, which ensures maximum compatibility with older devices. Options:
    • baseline: Maximum compatibility (recommended for web)
    • main: Better compression, good compatibility
    • high: Best compression, newer devices only
    • Use main or high if you don't need to support older devices.
  • -level 3.0: Sets the H.264 level, which limits bitrate and resolution. Level 3.0 supports up to 720p@30fps. Increase to 3.1 for 720p@60fps or 4.0 for 1080p@30fps if needed.
  • -pix_fmt yuv420p: Sets pixel format to YUV 4:2:0 planar, which is required for maximum compatibility. This ensures the video works on all devices and browsers. Don't change this.
  • -c:a aac: Sets audio codec to AAC, which has excellent web compatibility.
  • -an: Removes audio from the output which can be helpful if you want it to auto-play in background. If not remove this and add -b:a 128k to set audio bitrate instead.
  • -ss 1: Starts encoding from 2 seconds into the source video (seeks to that position). I often do this to skip any fade-in from the source video but remove it if you want to keep the start.
  • -t 5: Limits output duration to 5 seconds. Remove this to encode the entire video, or adjust the duration as needed. Long videos can use a lot of bandwidth which can be a problem on mobile plans still today.
  • -movflags faststart: Moves metadata to the beginning of the file, enabling progressive download and faster playback start. Always include this for web videos - it allows browsers to start playing before the entire file downloads.
  • output.mp4: The output filename. Change this to your desired output file name.

An MP4 with fade effects for looping

This command adds fade-in and fade-out effects, perfect for seamless looping videos:

ffmpeg -i fish.mov -vf "scale=960:540,crop=360:540,fade=in:st=0:d=1,fade=out:st=10:d=1" -c:v libx264 -crf 23 -profile:v baseline -level 3.0 -pix_fmt yuv420p -c:a aac -an -t 11 -movflags faststart fishf.mp4
Explain the options

The key difference here is the video filter chain:

  • -vf: Video filter (same as -filter:v). The filter chain includes:
    • fade=in:st=0:d=1: Fade in starting at 0 seconds, duration of 1 second
      • st=0 is the start time of the fade
      • d=1 is the fade duration
      • Adjust d=1 to make fades longer/shorter (e.g., d=0.5 for faster fade, d=2 for slower)
    • fade=out:st=10:d=1: Fade out starting at 10 seconds, duration of 1 second
      • st=10 should match your video duration minus fade duration
      • For an 11-second video, start fade-out at 10 seconds so it completes by 11 seconds
  • -t 11: Sets total duration to 11 seconds. Make sure this matches your fade-out timing.

Tips

  • When putting multiple videos on the same page use different durations for each so they loop at different times for a nice effect.
  • This is great for background videos, hero sections, or any video that loops continuously. The fades create a seamless transition when the video restarts.
  • Use #t=1 if you want to skip the initial first second of video where it is fading in on the initial page load.

A video poster image

A poster image displays before the video plays and provides a preview. It's also useful if the user has video off or their browser decides not to download it:

ffmpeg -y -i input.mov -filter:v "scale=960:540,crop=360:540" -vframes 1 -ss 1 poster.webp
Explain the options
  • -vframes 1: Extracts exactly 1 frame. This is essential for creating a poster image.
  • -ss 1: Seeks to 1 second into the video before extracting the frame. You can either choose a good image or the first frame after your fade-in.
  • poster.webp: Output format is WebP, which provides excellent compression and compatibility today.
  • The filter chain scale=960:540,crop=360:540 ensures the poster matches your video dimensions exactly. Adjust this to match what you did on the video encoding.

Tips

  • For the best poster image, preview your video and choose a frame that's visually interesting and representative.
  • Try a few different -ss values to find the perfect frame or scrub through using a video playback tool first.

HTML5 video tag best practices

Once you have your optimized video and poster image, here's how to use them in HTML:

<video
  src="https://mysite.com/videos/output.mp4#1"
  poster="https://mysite.com/videos/poster.webp"
  type="video/mp4"
  playsinline
  autoplay
  muted
  loop
  alt="A description of the video"
/>
Breakdown the options

Let's break down each attribute:

  • src: The video file URL. The #t=1 fragment starts playback at 1 second which can skip the initial fade-in. Match this to whatever your video fade-in length was.
  • poster: The poster image URL. This displays before the video plays and while it's loading. Always include this for better user experience and faster perceived load times.
  • type="video/mp4": Explicitly declares the MIME type. This helps browsers determine if they can play the video without downloading it first.
  • playsinline: Critical for iOS devices. Without this, videos on iOS will open in fullscreen. Include this for inline playback on mobile.
  • autoplay: Automatically starts playback when the page loads. Note: Browsers may block autoplay with sound, but muted videos usually autoplay successfully. Add muted attribute if autoplay is blocked.
  • loop: Makes the video loop continuously. Perfect for background videos or ambient content.
  • alt: Provides alternative text for accessibility. While not standard for <video>, it's good practice for screen readers and SEO.

Additional attributes to consider:

  • muted: Mutes the video. Often required for autoplay to work in many browsers.
  • preload="metadata": Loads video metadata only (recommended). Options: none, metadata, auto.
  • controls: Shows browser's default video controls. Omit for background/ambient videos.
  • width and height: Explicit dimensions help prevent layout shift during load.

Hope that helps!

Damien

0 responses

  1. Avatar for

    Information is only used to show your comment. See my Privacy Policy.