Home > Software design >  Upload large video to GCS use signed url but video is broken
Upload large video to GCS use signed url but video is broken

Time:02-14

I have a application for Google App Engine(GAE), using Vue.js on the frontend and Flask on the backend. My app allows users to upload large video and will analyze it. But since GAE's upload size limit is 32MB, so I allow users to upload directly to Google Cloud Storage(GCS) using signed url.

The problem I am facing is that the user can successfully upload the video to GCS, but on the backend(flask) when downloading the video for analysis, get the error below:

*** OSError: MoviePy error: failed to read the duration of file /tmp/source_video.mp4.
Here are the file infos returned by ffmpeg:

ffmpeg version 4.2.2-static https://johnvansickle.com/ffmpeg/  Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8 (Debian 8.3.0-6)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7444500] Format mov,mp4,m4a,3gp,3g2,mj2 detected only with low score of 1, misdetection possible!
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7444500] moov atom not found
/tmp/source_video.mp4: Invalid data found when processing input

Flask code download:

class Analyser:
    def __init__(self):
        self.gcs_bucket = 'bucket_name'
        self.gcs_blob_video = 'videos/'

    def __storage_bucket(self):
        client = storage.Client()
        bucket = client.get_bucket(self.gcs_bucket)
        bucket.cors = [
            {
                "origin": ["*"],
                "responseHeader": [
                    "Access-Control-Allow-Origin"
                ],
                "method": ['PUT', 'POST', 'GET'],
                "maxAgeSeconds": 3600
            }
        ]
        bucket.patch()
        return bucket

    def __generate_upload_signed_url(self, bucket, blob):
        blob = bucket.blob(blob)
        return blob.generate_signed_url(
            version='v4',
            expiration=datetime.timedelta(minutes=15),
            method='PUT',
        )
   
    def analyze_video(self, pid):
        src_filepath = '/tmp/source_video.mp4'

        bucket = self.__storage_bucket()
        blob = bucket.blob(self.gcs_blob_video   'filename.mp4')
        blob.download_to_filename(src_filepath)

        #error is here
        video = VideoFileClip(src_filepath)

Vuejs code upload:

note: Uploaded successfully, on gcs there is a file to upload.

async uploadVideo(_: any, video: File): Promise<string> {
      signed_url = "https://storage.googleapis.com/bucket_name...." #signed url is return from flask
      const formData = new FormData();
      formData.append('file', video);
      const response_upload_file = await fetch(
        signed_url,
        {
          method: 'PUT',
          body: formData
        }
      )
      return true
}

I've searched on google quite a bit and still haven't found a solution.

I really don't know if it's broken during the upload or when I download for analysis. I would be very grateful if someone could suggest me a solution to solve this problem.

Thanks for reading.

CodePudding user response:

You are using formData with the HTTP PUT method which corrupts the upload as a binary data stream is expected and not MIME data.

To use formdata:

Upload an object with HTML forms

  • Related