getDownloadUrl on an Array of videos

Okay Wix Velo masters, I come to you again with another quandary. I am needing to use the getDownloadUrl() function from media-manager-backend, for every video in an array, and then generate a new array with the proper download URLs instead of the useless wix:video ones.

I’ve been at it a couple days, and in all my attempts, the closest I got was having console.log show all of them, and indeed it does, and it showed that the function was actually getting the urls I need, BUT they are not in an array. Whenever I try to put it into an array, it simply does nothing, or creates an array of empty values.

Here is the failed code as I have it currently, to show what I’m trying to achieve. I already found all the videos and put them in an array called “videoArray”, and now I just need to get the download Urls into a new array called “urlVideoArray”:

 var urlVideoArray = []
  videoArray.forEach(async(video) => {
    video = await mediaManager.getDownloadUrl(video);
    
    urlVideoArray.push(video)
      });
  console.log("urlVideoArray", urlVideoArray)

The result of the above code is just an empty array.

But when I do this:

videoArray.forEach(async(video) => {
    video = await mediaManager.getDownloadUrl(video);
    console.log("video", video)
    }); 

I get this result, proving that it is getting the urls I need. But here it’s obviously just listing each one inside the “forEach” statement, as they come through:

Does anyone have any idea how I might could achieve my goal of creating a new array from the results of the getDownloadUrl function? I can’t for the life of me figure out why this isn’t working. I’ve used the forEach and .push methods elsewhere in this code when working with arrays, to create new arrays, and it works perfectly. But here it seems to have a problem with the addition of the getDownloadUrl function.

I’m sure it’s something simple I’m missing here so any help is appreciated!

Thanks,

Jared

Hi Jared,

The problem is that the forEach loop is just firing off a bunch of async calls and then you log the urlVideoArray before they are finished. Instead of using the forEach loop, try changing it to a for of loop instead. The for of loop will handle the await call like you are expecting. It should look like something like this:

let urlVideoArray = [];
for (const fileName of videoArray) {
let video = await mediaManager.getDownloadUrl(fileName);
urlVideoArray.push(video);
});
console.log(“urlVideoArray”, urlVideoArray);

Thank you! Quick question though, I’m working with the code sample you gave there, and it’s having a problem with await being in there without async. So I’m trying to put it in there, but I’m not getting any results from it. Just a blank array. Here’s my most recent attempt which didn’t work:

   let urlVideoArray = [];
  (async () => { 
    for (const fileName of videoArray) {
    let video = await mediaManager.getDownloadUrl(fileName); 
    urlVideoArray.push(video)
      }
  })
  console.log("urlVideoArray", urlVideoArray) 

I also tried doing “for await” but that didn’t work either. Definitely scratching my head over this one.

I appreciate the help.

Hi Jared. Yeah, the function that holds the for loop will need to be defined as async. Wrapping it up in an anonymous async function has the same effect as before, where it fires off a async call and then logs urlVideoArray before it is finished. Try moving the console.log inside of the anonymous function like this:

(async()=>{
let urlVideoArray=[];
for(constfileNameofvideoArray {
let video=awaitmediaManager.getDownloadUrl(fileName);
urlVideoArray.push(video)
}
console.log(“urlVideoArray”,urlVideoArray)

// Note that any other processing on urlVideoArray needs to be done in this function as well. 

});

Okay that makes sense, but it still isn’t doing anything for some reason. It occurs to me that something else in my full code may be the culprit. Here is the full code that I’m building in a web module, to give you proper context. Do you see anything here that would be holding this up?

Essentially I am just querying a collection, isolating the results to just the videoField in a new array (called videoArray). Then I simply need to change that array to the proper download URLs. What am I doing wrong here?

'use strict';

import wixData from 'wix-data';
import { mediaManager } from 'wix-media-backend';

export function queryArrayTest() {
  
 var videoArray = []
 
     wixData.query("AllGuestUploads-Video")
      .eq("eventId", "bbfd431b-f957-40bc-89e9-d05c19e6edc2")
      .eq("includeInHighlight", true)
      .ascending("chapterNumber", "orderInCategory")
      .find()
      .then((results) => {
     
      let fullUploadData = results.items
      console.log("fullUploadData", fullUploadData)
    // Create new array for the videoField //
    videoArray = fullUploadData.map(({ videoField }) => videoField)
      console.log("videoArray", videoArray),
      
// GET DOWNLOAD URLS OF VIDEOS //

  (async() => { 
    let urlVideoArray = [];
    
    for (const fileName of videoArray) {
      let video = await mediaManager.getDownloadUrl(fileName);
      urlVideoArray.push(video) 
  }
  console.log("urlVideoArray", urlVideoArray)
 });
  
 });
 }

When I run it, I only get the two arrays, fullUploadData & videoArray, which are both working as expected. It’s just this getDownloadUrl thing that I can’t get working in this case.

Ok, try this. Change the queryArrayTest() to async and then remove the anonymous function around the loop to get the urls. So it looks like this:

‘use strict’;

import wixData from ‘wix-data’;
import { mediaManager } from ‘wix-media-backend’;

export async function queryArrayTest() {

var videoArray = []

wixData.query(“AllGuestUploads-Video”)
.eq(“eventId”, “bbfd431b-f957-40bc-89e9-d05c19e6edc2”)
.eq(“includeInHighlight”, true)
.ascending(“chapterNumber”, “orderInCategory”)
.find()
.then((results) => {

  let fullUploadData = results.items 
  console.log("fullUploadData", fullUploadData) 
  // Create new array for the videoField // 
  videoArray = fullUploadData.map(({ videoField }) => videoField) 
  console.log("videoArray", videoArray), 

// GET DOWNLOAD URLS OF VIDEOS //

  let urlVideoArray = []; 

  for (const fileName of videoArray) { 
    let video = await mediaManager.getDownloadUrl(fileName); 
    urlVideoArray.push(video)  
  } 
  console.log("urlVideoArray", urlVideoArray) 

}); 

}

Okay, I’m glad to know I’m on the right track, because that’s what I was trying next! Unfortunately it still didn’t work :confused:

I put the code exactly as you said, except that I had to close out the .then((results) part before moving on because it was throwing an error about the await line being inside that (saying it needs to be inside an async function). Closing out that part before it got rid of the red line under await. Other than that, it’s the same.

'use strict';

import wixData from 'wix-data';
import { mediaManager } from 'wix-media-backend';

export async function queryArrayTest2() {


 var videoArray = []


     wixData.query("AllGuestUploads-Video")
      .eq("eventId", "bbfd431b-f957-40bc-89e9-d05c19e6edc2")
      .eq("includeInHighlight", true)
      .ascending("chapterNumber", "orderInCategory")
      .find()
      .then((results) => {
     
      let fullUploadData = results.items
      console.log("fullUploadData", fullUploadData),
    // Create new array for the videoField //
    videoArray = fullUploadData.map(({ videoField }) => videoField)
      console.log("videoArray", videoArray)
     
      }); // <-- This is the only thing I changed in your code sample //
// GET DOWNLOAD URLS OF VIDEOS //

    let urlVideoArray = [];
    
    for (const fileName of videoArray) {
      let video = await mediaManager.getDownloadUrl(fileName);
   
      urlVideoArray.push(video)
    
  }
  console.log("urlVideoArray", urlVideoArray)
 }
  
        

And this was my result. The urlVideoArray came first, and was empty. The other two arrays still had results.

And just for clarity, here’s the error it gave me on the await line before I changed the code:

Ok, I was afraid that wouldn’t like the await in the promise. Another thing to try is to await the database query as well and not have the promise at all. Something like this:
‘use strict’;

import wixData from ‘wix-data’;
import { mediaManager } from ‘wix-media-backend’;

export async function queryArrayTest() {

var videoArray = []

let results = await wixData.query("AllGuestUploads-Video") 
  .eq("eventId", "bbfd431b-f957-40bc-89e9-d05c19e6edc2") 
  .eq("includeInHighlight", true) 
  .ascending("chapterNumber", "orderInCategory") 
  .find(); 
 
  let fullUploadData = results.items 
  console.log("fullUploadData", fullUploadData) 
  
  // Create new array for the videoField // 
  videoArray = fullUploadData.map(({ videoField }) => videoField) 
  console.log("videoArray", videoArray), 

// GET DOWNLOAD URLS OF VIDEOS //

let urlVideoArray = []; 

for (const fileName of videoArray) { 
  let video = await mediaManager.getDownloadUrl(fileName); 
  urlVideoArray.push(video)  
} 
console.log("urlVideoArray", urlVideoArray) 

}

Ok that method seems promising (pun intended), except it threw this error at me:


I really appreciate your help with this by the way! It’s a frustrating one for sure. lol

Here’s the code I used, as copied from yours. Almost exactly the same, except I removed the comma after the videoArray console.log:

 'use strict';

import wixData from 'wix-data';
import { mediaManager } from 'wix-media-backend';

export async function queryArrayTest2() {


 var videoArray = []

    
    let results = await wixData.query("AllGuestUploads-Video")
      .eq("eventId", "bbfd431b-f957-40bc-89e9-d05c19e6edc2")
      .eq("includeInHighlight", true)
      .ascending("chapterNumber", "orderInCategory")
      .find();
     
      let fullUploadData = results.items
      console.log("fullUploadData", fullUploadData)
    // Create new array for the videoField //
    videoArray = fullUploadData.map(({ videoField }) => videoField)
      console.log("videoArray", videoArray)
     
      
// GET DOWNLOAD URLS OF VIDEOS //

    let urlVideoArray = [];
    
    for (const fileName of videoArray) {
      let video = await mediaManager.getDownloadUrl(fileName);
   
      urlVideoArray.push(video)
    
  }
  console.log("urlVideoArray", urlVideoArray)

 }
  
        

@jbelt40 still making progress! So it looks like awaiting the query worked. Can you confirm that the values in fullUploadData and videoArray are valid? It looks like the call to getDownloadUrl may have failed for some reason. You can try to catch the error by changing the call to:

let video = await mediaManager.getDownloadUrl(fileName).catch(err => console.log('Error: ', e));

@robmich Yeah that part worked, the fullUploadData and videoArray are valid, and contain all the expected info. But still no luck on the urlVideoArray. I tried catching the error as you suggested, but saw nothing new, just the same “request timed-out after 14 seconds” message as the above photo.

Put it in as you suggested:

 // GET DOWNLOAD URLS OF VIDEOS //

    let urlVideoArray = [];
    
    for (const fileName of videoArray) {
      let video = await mediaManager.getDownloadUrl(fileName).catch(err => 
      console.log('Error', err));
      
      urlVideoArray.push(video)
    
  }
  console.log("urlVideoArray", urlVideoArray)

 }

@robmich it’s weird, because I can see that the getDownloadUrl function works, because if i console.log(video), inside the loop, it logs all 34 video download urls individually, and they’re all the correct Urls I’m trying to get. So it’s doing it, but I just can’t get it to put them into an array…

@jbelt40 Sorry for the slow response - busy weekend. Were you able to get this working? I don’t see a reason that this code wouldn’t be working. How are you calling the function? From the frontend or the backend? One thing to try is to return urlVideoArray and then do a console log from the caller? Just curious if it is returning a valid array of Urls but just not logging it for some reason.

@robmich No worries man. I wasn’t able to get it working in the way I was originally attempting, but I found a kind of jerry-rigged workaround to get what I was after.

My site has a feature where guests upload videos, and those are the videos that I need to access in a downloadable Url. So, I decided to try to capture that info individually when they upload, instead of trying to get them all at once later on. At first, I tried using the getDownloadUrl function in a beforeInsert hook, but it still wouldn’t work for me. The only media-backend function that I could get working in that was the playbackUrl one, but of course that url doesn’t work for my purposes (I need a url that a third party api can read/download).

SO my jerry-rigged solution was to create a button on the page immediately following the upload page, where they “Review & Edit” what they uploaded before submitting it. The button is then linked in the editor to the videoField of the currentItem, the way you would if you wanted the guest to be able to download it. Then, in the code, I assigned the .link value of that button to a new “downloadUrl” collection field via .setFieldValue. Lastly, I set the button to “hidden”.

Now, every time someone uploads a video, the item in the collection will also have a url that I can use, which weirdly is not one that I can access from any of their api code it seems (these urls end with “/file” which the api ones didn’t from what I could tell :thinking:). So it’s a little bit of a silly approach, but it works for me haha

*By the way, just to answer your questions, I was calling it from the backend, using a web module, and this weekend I did try console logging from every possible point in the code I could think of, just to get the best picture of what is happening and where the problem begins. But I couldn’t find anything. It seemed to do everything totally fine, until it gets to that function. Then, depending on how I attempted it, it would either be a blank array, or an array of 34 blank objects for some reason. It did that in my beforeInsert hook attempt as well. Instead of a url, it would only return “{}” to the collection.

So I honestly have no clue what’s going on there, and I’m glad it’s not just me who is struggling to figure it out haha aside from the documentation, there’s very little examples out there of the media-backend api, so it’s difficult to research possible errors, but I’ll keep my eyes peeled for any more insight on this in the future.For now my jerry-rigged method will do the job though so I’ll go with that! haha Thank you very much for your help with this. I really appreciate it!

@jbelt40 Glad you were able to get a workaround! I’m definitely going to experiment around with this some more. The behavior you are seeing is really strange!