Video : thumbnail

@Manu.n

Is this code still operational? I’m getting this error:

I found Peeaklink works pretty nicely with a lot of video-hosting sites, including Glide’s storage.

Hm. I have no idea how to set this up.

@Manu.n I got it working again. I had to place a value in the second field. Disregard!

My setup was to send the link to Make, generate the video thumbnail through Peekalink and update its thumbnail back to Glide.

I have the same issue, what did you fill ?

Nevermind I added the time and its now working this is how

Ya…the second field needs to be filled in. This XC column should REALLY be a Glide sponsored plugin column @mark

5 Likes

Yup its a must

Just jumping in here to say thanks! It worked perfectly, thanks Manu :raised_hands:

Hi @Manu.n , does this still work?

https://video-thumbnail-v1.manun2.repl.co/

For some reason this link is giving an error :frowning:

If you’re looking for a YouTube thumbnail there’s a native column for that now.

1 Like

Thanks. Unfortunately, I’m looking for thumbnails for videos I’m pulling from Airtable’s video column, so this won’t work for me. @Manu.n 's code seems to be the only solution for me.

@Robert_Petitto tagging you in case you habe any update

Gotcha. Ya haven’t seen @Manu.n in over 2 years but would be great if he’d come back :brain:lol

Replit changed their pricing structure a few days ago, so a lot of these code repositories that were hosted for free were shut down. I had used @Manu.n’s code when he initially created it, but I didn’t want to rely on someone else maintaining it for the exact case that it may disappear at some point, so I made a copy of the code for myself. If you simply put this in a javascript column, and pass the url in the p1 parameter and a 1 for the p2 parameter, it will do the exact same thing. It does not rely on hosting the code with a third party. I don’t know if @Manu.n ever made improvements to the code over the past couple of years and I don’t remember if I ever tweaked it myself, but this is pretty much what he had initially, and it has worked pretty well for me for the most part. These days you could probably ask ChatGPT for the same thing, which may or may not provide a better method. Since this code has been working for me, I haven’t explored if there is anything better.

let YTQuality = 
{
  "0" : "0",
  "1" : "1",
  "2" : "2",
  "3" : "3",
  "low" : 'sddefault',
  "low0" : 'sddefault',
  "low1" : 'sd1',
  "low2" : 'sd2',
  "low3" : 'sd3',
  "medium" : "mqdefault",
  "medium0" : "mqdefault",
  "medium1" : "mq1",
  "medium2" : "mq2",
  "medium3" : "mq3",
  "high" : "hqdefault",
  "high0" : "hqdefault",
  "high1" : "hq1",
  "high2" : "hq2",
  "high3" : "hq3",
  "max" : "maxresdefault",
  "max0" : "maxresdefault",
  "max1" : "maxres1",
  "max2" : "maxres2",
  "max3" : "maxres3"
}

// youtube thumbnail (base)
// quality = empty or : 0, 1, 2, 3, low0, low1, low2, low3, medium0, medium1, medium2, medium3, high0, high1, high2, high3, max0, max1, max2, max3
function get_youtube_thumbnail(url, quality) {
  if (url) {
    var video_id, thumbnail, result;

    result = url.match(
      /(?:youtu\.be\/|youtube\.com(?:\/embed\/|\/v\/|\/watch\?v=|\/user\/\S+|\/ytscreeningroom\?v=))([\w\-]{10,12})\b/
    );

    video_id = result[1];

    if (video_id) {
      let quality_key = YTQuality[quality];

      if (quality_key == undefined || quality_key == "") {
        quality_key = "sddefault";
      }

      var thumbnail =
        "https://img.youtube.com/vi/" + video_id + "/" + quality_key + ".jpg";
      return thumbnail;
    }
  }
  return false;
 
}

// video thumbnail
async function thumbnail(url, ctime, imgw, imgh) {
  return new Promise((resolve, reject) => {

    var video = document.createElement('video');

    var dataURI;
    video.src = url;
    video.type = "video/mp4";
    video.crossOrigin = "anonymous";

    if (video.duration > ctime)
      ctime = video.duration;

    video.load();
    video.currentTime = ctime;

    video.addEventListener('loadeddata', function (e) {
      createImage();
    }, false);

    function createImage() {
      var canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d');
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;

      if (imgw != 0) {
        canvas.width = imgw;
      }

      if (imgh != 0) {
        canvas.height = imgh;
      }
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      dataURI = canvas.toDataURL('image/jpeg');
      resolve(dataURI);
    }
  });
}

let cache = new Map();


  url = p1 ?? "";
  ctime = p2; // ?? 0.01;
  imgw = 0 // imgw ?? 0;
  imgh = 0 // imgh ?? 0;

  if (url == '')
    return;


  if (
    url.search("https://youtu") > -1 ||
    url.search("https://www.youtu") > -1
  ) {
    let dataURI3 = get_youtube_thumbnail(url, ctime);
    return dataURI3;
  }

  let cacheKey = url + ctime + imgw + imgh;

  ctime = ctime.replace(',','.');
  ctime = parseFloat(ctime);
  if (ctime == 0)
    ctime = 1; //0.01;

  let ret = cache.get(cacheKey);

  if (ret == undefined) {
    let dataURI2 = await thumbnail(url, Math.abs(ctime), imgw, imgh);

    ret = dataURI2;
    cache.set(cacheKey, ret);
  }

  return ret;
3 Likes

Just peeking at the code I shared, there is already logic to handle if if the p1 url is empty, so there shouldn’t be anything you need to change. Just make sure you are referring to a column that only filled when when the type is ‘Video’.

Otherwise, add the type as a p3 parameter, look for this piece of code…

  if (url == '')
    return;

and modifiy it to look like this.

  if (url == '' || p3!='Video')
    return;

That should be the only thing you need to change.

1 Like

This worked perfectly! Thank you so much!

1 Like

Thanks so much again for putting this script out there. It’s worked, however, like a previous user earlier on this thread who worked with the hosted version of this script, I’m getting some of the thumbnail images returned as black, and not an image. Is there any fix to the code that could solve this? See example.

I think I was that previous user.

I don’t have an answer to the random black images. It has happened to me on occasion but it’s never been critical for anything I used it for. Sometimes closing and reopening the app solved the issue, but it’s completely random. If it’s not a YouTube video, it has to download and cache the video, go a certain number of seconds into the video to basically get screenshot from that specified point in time in the video. It’s actually doing a bit of processing, and sometimes it times out either downloading the video or processing it for the image. The script would probably need some error handling to account for these failures and retry if necessary. I haven’t personally explored any improvements to make the code better. I suppose someone could run it through ChatGPT to see if it offers any improvements to the code.

1 Like

Thanks Jeff! I’ll have my dev look into how we might improve it. Interestingly, the black images only seem to be appearing for PC/Windows, not for Chrome on Mac. Essentially for us, I think we’ll want to implement a process where the images get saved as JPGs from videos and stored, and that way, they won’t need to keep getting reprocessed/stored in cache etc.

1 Like