Skip to content

Commit

Permalink
feat: added uploadLocalVideo method
Browse files Browse the repository at this point in the history
 + aws-sdk npm package
 + mime-types npm package
 + 3 endpoints
 + 1 endpoint renamed
  • Loading branch information
madkarmaa committed Jan 30, 2024
1 parent 303516a commit 78445d8
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 5 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ node_modules/
package-lock.json
/*test*
/*temp*
dist/
dist/
/*.mp4
website-resources/
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
"author": "madkarma",
"license": "MIT",
"dependencies": {
"aws-sdk": "^2.1546.0",
"axios": "^1.6.5",
"convert-units": "^2.3.4",
"get-video-duration": "^4.1.0"
"get-video-duration": "^4.1.0",
"mime-types": "^2.1.35"
},
"devDependencies": {
"jsdoc-to-markdown": "^7.1.0"
Expand Down
6 changes: 4 additions & 2 deletions src/constants/endpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ const endpoints = {
LABELS: BASE_URL + '/labels',
EXTRACT: (encodedUrl) => BASE_URL + '/extract?url=' + encodedUrl,
UPLOAD_FROM_URL: BASE_URL + '/uploads/videos',
TRANSCODE_FROM_URL: (videoId) => BASE_URL + '/transcode/' + videoId,
INIT_UPLOAD_VIDEO: (fileSize) => BASE_URL + '/uploads/shortcode?size=' + fileSize + '&version=unknown',
TRANSCODE_VIDEO: (videoId) => BASE_URL + '/transcode/' + videoId,
INIT_UPLOAD_LOCAL_VIDEO: (fileSize) => BASE_URL + '/uploads/shortcode?size=' + fileSize + '&version=unknown',
VIDEOS: BASE_URL + '/videos?sort=date_added',
VIDEO: (shortcode) => BASE_URL + '/videos/' + shortcode,
RENAME_VIDEO: (shortcode) => BASE_URL + '/videos/' + shortcode + '/rename',
INIT_VIDEO: (shortcode) => BASE_URL + '/videos/' + shortcode + '/initialize',
TRACK_UPLOAD: (shortcode) => BASE_URL + '/uploads/' + shortcode + '/track',
};

module.exports = endpoints;
89 changes: 88 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ const axios = require('axios').default;
const { URL } = require('node:url');
const { getVideoDurationInSeconds } = require('get-video-duration');
const convert = require('convert-units');
const fs = require('node:fs');
const path = require('node:path');
const { lookup } = require('mime-types');
const endpoints = require('./constants/endpoints.js');
const { getSha256 } = require('./utils');
const S3 = require('aws-sdk/clients/s3.js');

axios.interceptors.response.use(
function (response) {
Expand Down Expand Up @@ -166,7 +171,7 @@ class StreamableClient {

return (
await axios.post(
endpoints.TRANSCODE_FROM_URL(uploadedVideoData.shortcode),
endpoints.TRANSCODE_VIDEO(uploadedVideoData.shortcode),
{
extractor: extractedVideoData.extractor,
headers: extractedVideoData.headers,
Expand Down Expand Up @@ -246,6 +251,88 @@ class StreamableClient {
async renameVideoTitle(shortcode, newTitle) {
await axios.post(endpoints.RENAME_VIDEO(shortcode), { title: newTitle }, { headers: this.#headers });
}

/**
* Upload a local video
* @param {String} videoPath The path to the video file
* @returns {Promise<object>} The uploaded video's data
*/
async uploadLocalVideo(videoPath) {
videoPath = path.resolve(videoPath);

if (!lookup(videoPath).startsWith('video')) return console.error('Please provide a video file!');

const { size: videoSize } = fs.statSync(videoPath);

const uploadMetaData = (await axios.get(endpoints.INIT_UPLOAD_LOCAL_VIDEO(videoSize), { headers: this.#headers })).data; // prettier-ignore

if (!uploadMetaData?.fields) return console.error('Cannot retrieve server upload headers!');

await axios.post(
endpoints.INIT_VIDEO(uploadMetaData.shortcode),
{
original_name: path.basename(videoPath),
original_size: videoSize,
title: path.parse(videoPath).name,
upload_source: 'web',
},
{ headers: this.#headers }
);

function uploadToBucket() {
return new Promise((resolve, reject) => {
const clockSkew = uploadMetaData.time ? uploadMetaData.time * 1000 - new Date().getTime() : 0;

const bucket = new S3({
apiVersion: '2006-03-01',
region: 'us-east-1',
credentials: uploadMetaData['credentials'],
useAccelerateEndpoint: uploadMetaData.accelerated,
maxRetries: 15,
systemClockOffset: clockSkew,
});

const upload = bucket.upload(
{
Key: uploadMetaData['key'],
Body: fs.createReadStream(videoPath),
Bucket: uploadMetaData['bucket'],
ACL: 'public-read',
},
{
queueSize: 3,
},
(err, data) => {
if (err) reject(err);
if (data) resolve(data);
}
);
});
}

let awsUploadData;
try {
awsUploadData = await uploadToBucket();
} catch (error) {
return console.error(error);
}

if (!awsUploadData) return console.error('Could not upload to AWS servers!');

await axios.post(
endpoints.TRACK_UPLOAD(uploadMetaData.shortcode),
{ event: 'complete' },
{ headers: this.#headers }
);

return (
await axios.post(
endpoints.TRANSCODE_VIDEO(uploadMetaData.shortcode),
{ ...uploadMetaData.transcoder_options }, // prettier-ignore
{ headers: this.#headers }
)
).data;
}
}

module.exports = StreamableClient;

0 comments on commit 78445d8

Please sign in to comment.