Skip to content

Instantly share code, notes, and snippets.

@chris9753
Created December 18, 2016 18:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chris9753/86121a07c4aa27fcd654d16133799d30 to your computer and use it in GitHub Desktop.
Save chris9753/86121a07c4aa27fcd654d16133799d30 to your computer and use it in GitHub Desktop.
/* ----- GENERAL ARCHITECTURE--->
not valid
<-respond with error
|
|
|
|
+------------------------------------------------------------------------+
| FFMPEG | |
+------------------------------------------------------------------------+
|
|
busboy |
+------------------------------------------> |
| optimistically retrieve enough bytes |
| of file to check if valid image frame | valid
| |
multipart------+--------------------------------------------v-------------stream of frames+---------+---------->
upload ^ 200 ok with file location from s3
| (finished video processing)
|
+------------------+----+-----------------+------------^
| upload | | transcode |
| to s3 | | transform |
| | | |
| | | |
+-----------+------+ +-----------------+
|
|
SSE |
|
|
|
+--^--------------
(file is ready and uploaded into s3)
--- GENERAL ARCHITECTURE---> */
export async function uploadVideo(req, resFromNode) {
const user = req.user;
var fsImpl = new S3FS('instaclone9753', {
accessKeyId: 'AKIAIXA5AKJQB7C3ZHCQ',
secretAccessKey: '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'
});
req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
const imageFrames = [];
const bufferHandler = (chunk) => {
//change this to optimistically calculate number of bytes necessary needed to retrieve metadata and offload an appropriate buffer
if (Buffer.concat(imageFrames).length < 4000000) {
imageFrames.push(chunk);
} else {
file.removeListener('data', bufferHandler);
imageFrames.push(chunk);
file.pause();
file.unshift(Buffer.concat(imageFrames));
checkIfStreamValid(imageFrames, (err, res) => {
if (err) {
resFromNode.header('Connection', 'close');
return resFromNode.status(415).json("This file has not met the standards");
}
// if file is valid call unshift put the data back on the stream and then pipe it into s3
const key = crypto.randomBytes(10).toString('hex');
const hashFilename = key + '-' + filename;
const params = {
Bucket: fsImpl.bucket,
Key: hashFilename,
Body: file,
ContentType: "video/mp4"
};
//finally uploaded either the transformed or the original stream
fsImpl.s3.upload(params, function (err, data) {
console.log(err, data, "YO!")
resFromNode.json({
"success": true,
"payload": data.Location
});
}).on('httpUploadProgress', function (evt) {
console.log(evt);
pubsub.emit('uploadProgress', evt);
})
});
}
}
const listener = file.on('data', bufferHandler);
file.on('end', () => console.log("finished! buffering into memory!"));
function checkIfStreamValid(pseudoStream, cb) {
//use ffmpeg here to check if it is a valid video file;
const pseudoBuffer = Buffer.concat(pseudoStream)
console.log(pseudoBuffer);
const bufferStream = new PassThrough();
// Write your buffer
bufferStream.end(pseudoBuffer);
ffmpeg.ffprobe(bufferStream, function (err, metadata) {
if (metadata) cb(null, metadata);
console.log(err);
if (err) cb(true, null);
});
}
});
req.pipe(req.busboy);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment