Search code examples
google-cloud-platformgoogle-cloud-storageazure-video-indexer

Issue with using a video file on Google Cloud Storage as Input to Microsoft video Indexer


I use MicroSoft Video indexer to run Video intelligence and extract useful features/contents from user video inputs. I've been using the web interface, but now I'm needing to automate this by using the Rest API.

There are 2 approaches to specifying the video file to upload. One is ingesting raw bytes and the other is citing the address of a video file on the cloud (recommended). See the API doc.

The problem is that I'm having issues specifying a file on Google Cloud Storage bucket. I understand that you have to specify the URL of a publicly available file, which I'm doing by providing the signedURL of the video file. But it keeps giving me the error below which doesn't happen when I specify the address of the same video file uploaded to Cloudinary.

{
  "ErrorType": "INVALID_INPUT",
  "Message": "Url content type 'application/xml' is not supported. Only audio and video files are supported. You can find the supported types here: https://learn.microsoft.com/ro-ro/azure/media-services/media-services-media-encoder-standard-formats. Trace id: '7e9e2626-6dd3-4e9b-8b06-5991cfdb896c"
}

For reference, here are the 2 addresses:

  1. Cloudinary: https://res.cloudinary.com/account-id/video/upload/v1612773239/VideoAI/Elen_Hyundai_high.mp4
  2. GCS: https://storage.googleapis.com/project-id.appspot.com/video-files/filename?GoogleAccessId=firebase-adminsdk-some-service-account-key.com&Expires=1612857836&Signature=Rog3NWpzqXINxPWQl9sLLP8eDASNEglUehL6YkMB90YXRIWGk8PZOYGpUB9MVgTXKtFe4IjbR0tRuDUVhCeIhFTfL3kR2YXCZ3mqbOYOQlzfasq4YE4FtGiN40gNicjiLbJbq8vq4pMIwRfSirSOV92t9ev5ydPcW0BgICfd5n6QOhCvLx%2FpPgonCuGtK82Zyu21M%2BFRxuqmDTfCsZwP0fxfzwoZblusEFxIxpZFiXtow27EBYy3Dqv062UWhPuLhSyBKnFIHReaSaRcfwRVMF4Sw849eeMLGYdqHSy9LOVsw%2FcYTJenjM4bqoj1jqSduh8A%2FmGkN3rFRok3aT4qjw%3D%3D

I can provide the actual URL if you're needing to test it.


Solution

  • Ok, I solved this by encoding the query params path of the signedURL gotten from GCS before adding it to the videoUrl params sent to MicroSoft Video Indexer (MVI)

    const temp = signedURL.split('?')
    
    videoUrl = temp[0] + encodeURIComponent(`?${temp[1]}`)
    

    This is because MVI runs decodeURIComponent on the videoUrl - thus the goal is to make the result equal to the original url sent by GCS:

      const bucketFile = bucket.file(filePath)
      const [signedURL] = await bucketFile.getSignedUrl({
        action: 'read',
        expires: 3600 * 1000, // 1hr or add-your-expiration,
      })