Jordan voss
Jordan voss

Reputation: 13

How can I get recorded video from js to my Flask App?

I have a flask app that is supposed to record video and be able to send that video back to my python scripts to be then put into the database. I've tried to put it into a form but not too sure I'm doing it the right way. here is my js

  audio: false, 
  video:true
}; 

if (navigator.mediaDevices === undefined) {
  navigator.mediaDevices = {};
  navigator.mediaDevices.getUserMedia = function(constraintObj) {
      let getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
      if (!getUserMedia) {
          return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
      }
      return new Promise(function(resolve, reject) {
          getUserMedia.call(navigator, constraintObj, resolve, reject);
      });
  }
}else{
  navigator.mediaDevices.enumerateDevices()
  .then(devices => {
      devices.forEach(device=>{
          console.log(device.kind.toUpperCase(), device.label);
          //, device.deviceId
      })
  })
  .catch(err=>{
      console.log(err.name, err.message);
  })
}

navigator.mediaDevices.getUserMedia(constraintObj)
.then(function(mediaStreamObj) {
  //connect the media stream to the first video element
  let video = document.querySelector('video');
  if ("srcObject" in video) {
      video.srcObject = mediaStreamObj;
  } else {
      //old version
      video.src = window.URL.createObjectURL(mediaStreamObj);
  }
  
  video.onloadedmetadata = function(ev) {
      //show in the video element what is being captured by the webcam
      video.play();
  };
  let start = document.getElementById('startbtn');
  let stop = document.getElementById('btnStop');
  let vidSave = document.getElementById('vid2');
  let mediaRecorder = new MediaRecorder(mediaStreamObj);
  let chunks = [];
  
  start.addEventListener('click', (ev)=>{
      mediaRecorder.start();
      console.log(mediaRecorder.state);
  })
  stop.addEventListener('click', (ev)=>{
      mediaRecorder.stop();
      console.log(mediaRecorder.state);
  });
  mediaRecorder.ondataavailable = function(ev) {
      chunks.push(ev.data);
  }
  mediaRecorder.onstop = (ev)=>{
      let blob = new Blob(chunks, { 'type' : 'video/mp4;' });
      for (chunk in chunks) {
        console.log(chunk);
      }
      chunks = [];
      let videoURL = window.URL.createObjectURL(blob);
      vidSave.src = videoURL;
  }
  $.post('/video',
  {share: videoURL}, function(data) {

  })
})
});

and my route in my flask app

@main_bp.route('/video' , methods=['GET', 'POST'])
@login_required
def video():
    form = VideoForm()
    if form.validate_on_submit():
        flash('Video Saved Successfully!')
        vid = request.json['share']
        print(jsonify(vid))
        return redirect('home.html')
    return render_template('video.html', form=form, name=current_user.username)```

I also have a VideoForm class as I have been using that for my login forms but I'm not really sure what way the video is coming back to me, as json, images etc. here is the VideoForm

class VideoForm(FlaskForm):
    video = FileField('img')
    submit = SubmitField('Save Video')

If anyone knows how or has any tips to point me in the right direction at least that would be great! Thanks

Upvotes: 0

Views: 1380

Answers (1)

Detlef
Detlef

Reputation: 8552

You can either use a form of the type "multipart/form-data" to transfer the video.
With this variant, the data can be accessed in flask as a file (werkzeug.FileStorage).

let formData = new FormData();
formData.append('video', blob, "video.mp4");
$.ajax ({
  url: "/upload",
  type: "POST",
  data: formData,
  processData: false,
  contentType: false,
  success: function(resp){
    console.log(resp);
  }
});
@app.route('/upload', methods=['POST'])
def upload():
    video = request.files.get('video')
    if video: 
          
       # process the file object here! 

       return jsonify(success=True)
    return jsonify(success=False)

As a simple alternative, you can also send the data to the server in raw form.
In this case, the data fill the entire post-body and can either be loaded as a whole or from the stream (werkzeug.LimitedStream).

$.ajax ({
  url: "/upload",
  type: "POST",
  data: blob,
  contentType: "video/mp4",
  processData: false,
  success: function(resp){
    console.log(resp);
  }
});
@app.route('/upload', methods=['POST'])
def upload():
    if request.headers.get('Content-Type') == 'video/mp4':
        # load the full request data into memory
        # rawdata = request.get_data()
        
        # or use the stream 
        rawdata = request.stream.read()

        # process the data here!

        return jsonify(success=True)
    return jsonify(success=False)

Upvotes: 1

Related Questions