Solution 1 :

The trick is to have a container div that is what holds your video tag (as a child object). When there is an error, you delete the child object (video tag) and dynamically create a new image tag, that gets added as a replacement child into the container.

The result is: (within container div…) Delete the video tag and Replace with an image tag.
The user sees the video object replaced by an image.

See if this example code helps you to solve your problem:

<!DOCTYPE html>
<html>
<body>

<!-- should make the div's width & height to be same as video's display size -->
<!-- example code is assuming video is 600x400  -->

<div id="container_vid1" style="width:600px;" />
<video
      id="vid"
      controls
      
      autoplay
      controlsList="nodownload"
      preload="true"
      playsinline=""
      muted
      width="600"
      height="400"
    >
<source
    src="https://xxx.s3.eu-central-1.amazonaws.com/yyy/zzz.mp4"
    type="video/mp4"
    />
</video>

</div>

<script>

var path_to_img = "https://outbackpoolgp.com/wp-content/uploads/2016/11/640x400-water-mobile-3.jpg"; //# update this with image path
var vid = document.getElementById("vid"); //reference the video tag

vid.addEventListener( "error", (evt) => { handle_VideoError(evt); }, true);

function handle_VideoError(evt)
{
    alert(
            "Error from <video> element : " + evt.currentTarget.id
            + "n" //# looks better on new line
            + "File not found : "  + evt.currentTarget.currentSrc
         );
         
    //# access the parent div
    let container = document.getElementById("container_vid1");
                
    //# in div... remove any existing child < element(s) />
    while (container.firstChild)  
    { container.removeChild(container.firstChild); }
    
    //# create (& add to div) a new <img> element
    let tmpElement = document.createElement( "img");
    tmpElement.setAttribute("id", "vid"); //# set same id as previous video tag (if preferred)
    tmpElement.setAttribute("width", container.clientWidth );
    tmpElement.setAttribute("src", path_to_img );

    container.appendChild( tmpElement );
    
}

</script>

</body>

Solution 2 :

You could add the poster attribute to your video elements.

The poster attribute specifies an image to be shown while the video is downloading, or until the user hits the play button. If this is not included, the first frame of the video will be used instead.

Problem :

I am using a <video> tag to get an animation or each of my products like this:

    <video
      autoplay
      controlsList="nodownload"
      preload="true"
      playsinline=""
      muted
      width="600"
      height="840"
    >
      <source
        src="https://xxx.s3.eu-central-1.amazonaws.com/yyy/zzz.mp4"
        type="video/mp4"
      />
    </video>

However, some of my products do not have an animation, so instead I should load an image using the <img> tag as a fall back. So far I have only seen examples of img to img fallbacks, and I am curious what the fastest way to accomplish a vid to img fallback is.

Comments

Comment posted by Ram Ratan Bairar

add

Comment posted by Alien13

The poster attribute would not solve my problem, as it will show the image first, even in the case that the video exists.

Comment posted by Alien13

The poster attribute would not solve my problem, as it will show the image first, even in the case that the video exists.

By esgsw