0

So i have the following node code for uploading video to my node server:

    var fs = require('fs');

var videoExtensions = ['mp4','flv', 'mov'];
//Media object
function Media(file, targetDirectory) {
   this.file = file;
   this.targetDir = targetDirectory;
}

Media.prototype.isVideo = function () {
    return this.file.mimetype.indexOf('video') >= 0;
};
Media.prototype.getName = function () {
    return this.file.originalname.substr(0, this.file.originalname.indexOf('.'))
};

router.route('/moduleUpload')
    .post(function (request, response) {
        var media = new Media(request.files.file, '../user_resources/module/'+request.body.module_id+'/');
        if(!fs.existsSync('../user_resources/module/'+request.body.module_id+'/')){
            fs.mkdirSync('../user_resources/module/'+request.body.module_id+'/', 0766, function(err){
                if(err){
                    console.log(err);
                    response.send("ERROR! Can't make the directory! \n");    // echo the result back
                }
            });
        }
        convertVideos(media);
        response.status(200).json('user_resources/module/' + request.body.module_id + '/' + request.files.file.name);

    });


function convertVideos (media){
    var ffmpeg = require('fluent-ffmpeg');
    videoExtensions.forEach(function(extension){
        var proc = new ffmpeg({source: media.file.path, nolog: false})
            .withVideoCodec('libx264')
            .withVideoBitrate(800)
            .withAudioCodec('libvo_aacenc')
            .withAudioBitrate('128k')
            .withAudioChannels(2)
            .toFormat(extension)
            .saveToFile(media.targetDir+media.getName()+'.'+extension,
            function (retcode, error) {
                console.log('file has been converted succesfully');
            });
    });

}

Now instead of loading the video using an direct path i wish to load it using node

However i am not quite sure how to do this

Using direct path i would do something like this:

$scope.videos.push(
{
    sources: [
        {src: $sce.trustAsResourceUrl($scope.component.video_mp4_path), type: "video/mp4"}
    ]
}

where the video_mp4_path variable would be the direct path to the video ie: myproject/resources/video.mp4

However somehow i need to call node instead of an instant path.

as i said im not quite sure how to do this could someone point me in the right direction

1 Answer 1

1

You can upload, list and play using express and Multer which I found was relatively straightforward and worked reliably. In my case I used Angular and a regular browser for playback but the same principles should apply.

The following code extract worked for me:

Upload

// 
router.post('/web_video_upload', function(req, res) {
    //Log the request details
    Debug console.log(req.body);

    //Send a resposne
    res.send('Video Uploading');
    console.dir(req.files);
});

// POST: video upload route
// multer approach
var multer = require('multer');
app.use(multer({

    //Set dstination directory
    dest: path.resolve(__dirname, 'public', 'uploaded_videos'),

    //Rename file
    rename: function (fieldname, filename) {
        //Add the current date and time in ISO format, removing the last 'Z' character this usually
        //includes
        var dateNow = new Date();
        return filename + "_" + dateNow.toISOString().slice(0,-1)
    },

    //Log start of file upload
    onFileUploadStart: function (file) {
      console.log(file.originalname + ' is starting ...')
    },

    //Log end of file upload
    onFileUploadComplete: function (file) {
      console.log(file.originalname + ' uploaded to  ' + file.path)
      done=true;
    }

}));

List videos

// GET: route to return list of upload videos 
router.get('/video_list', function(req, res) {
    //Log the request details
    console.log(req.body);

    // Get the path for the uploaded_video directory - in a real app the video list would likely be taken from 
    // a database index table, but this is fine for us for now
    var _p;
    _p = path.resolve(__dirname, 'public', 'uploaded_videos');

    //Find all the files in the diectory and add to a JSON list to return
    var resp = [];
    fs.readdir(_p, function(err, list) {
        //Check if the list is undefined or empty first and if so just return 
        if ( typeof list == 'undefined' || !list ) {
            return;
        }
        for (var i = list.length - 1; i >= 0; i--) {

            // For each file in the directory add an id and filename to the response
            resp.push( 
                {"index": i,
                "file_name": list[i]}
            );
        }

        // Set the response to be sent
        res.json(resp);
    });
});

The above will return a JSON list of all the videos in your server directory. If you file name is the path to the video, you can use it in an angular view to create a table of videos and play them back using the HTML5 video tag (supported by pretty much all modern browsers).

Sign up to request clarification or add additional context in comments.

4 Comments

is this for uploading i need for downloading the file and insert it into videogular
@MarcRasmussen - sorry, misread. Added the code to respond to your angular app with the Video list from the server.
will the above code stream the video so i don't use direct path but instead use nodejs to stream the video to the player
@hmmm - the above will use regular HTML5 'streaming'. Video playback will start in a couple of seconds and you can move to the middle of the video etc. It is not adaptive bit rate streaming, if that is what you mean, but you may find you want a full featured javascript player like JWPlayer or BitDASH if that is what you need (will include adaptive bit rate, subtitles, languages support etc). I would guess you just want the above if it is basic video streaming.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.