I‘m currently working with video on demand process using aws lambda in nodeJs. I want to create video on demand with settings based on video file im storing inside S3 bucket. To make such a thing i would need to extract informations(like framerates, resolution, audio bit rate...) using MediaInfo.
I found this link https://aws.amazon.com/blogs/media/running-mediainfo-as-an-aws-lambda-function/ but it is done with python. Does anyone have idea or maybe other way how to do such a thing using nodeJs environment for lambda and not python ?
You can get this information using FFmpeg
and FFprobe
. In AWS Lambda you use the FFmpeg
Lambda layer ffmpeg-lambda-layer for FFmpeg
.
Here is the code for index.js
process.env.PATH = process.env.PATH + ':' + process.env['LAMBDA_TASK_ROOT']
const AWS = require('aws-sdk')
const { spawn, spawnSync } = require('child_process')
const { createReadStream, createWriteStream } = require('fs')
const s3 = new AWS.S3()
const ffprobePath = '/opt/bin/ffprobe'
const ffmpegPath = '/opt/bin/ffmpeg'
const allowedTypes = ['mov', 'mpg', 'mpeg', 'mp4', 'wmv', 'avi', 'webm']
const width = 300
const height = 300
module.exports.handler = async (event, context) => {
const srcKey = decodeURIComponent(event.Records[0].s3.object.key).replace(/\+/g, ' ')
const bucket = event.Records[0].s3.bucket.name
const target = s3.getSignedUrl('getObject', { Bucket: bucket, Key: srcKey, Expires: 1000 })
let fileType = srcKey.match(/\.\w+$/)
if (!fileType) {
throw new Error(`invalid file type found for key: ${srcKey}`)
}
fileType = fileType[0].slice(1)
if (allowedTypes.indexOf(fileType) === -1) {
throw new Error(`filetype: ${fileType} is not an allowed type`)
}
function getImageMediainfo() {
return new Promise((resolve, reject) => {
var output = [];
var ffprobe = spawn(ffprobePath, [
'-v', 'error',
'-select_streams', 'v',
'-show_entries',
'stream', //stream=width,height:stream_tags=rotate
'-of','json',
target
]);
ffprobe.stdout.on('data', function(data) {
output.push(data);
});
ffprobe.on('error', function(err) {
console.log('ffprobe error: ', err);
reject()
});
ffprobe.on('close', function() {
var outputStr = output.join('');
var jsonOut = {};
jsonOut = JSON.parse(outputStr);
console.log('outputStr', outputStr)
console.log('outputStr', jsonOut)
let framerates = jsonOut.streams[0].r_frame_rate // jsonOut.streams[0].avg_frame_rate
let resolution = {
width: jsonOut.streams[0].width,
height: jsonOut.streams[0].height
}
let audio_bit_rate = jsonOut.streams[0].bit_rate
console.log('framerates', framerates)
console.log('resolution', resolution)
console.log('audio_bit_rate', audio_bit_rate)
resolve()
})
})
}
await getImageMediainfo();
return console.log(`processed ${bucket}/${srcKey} successfully`)
}
Output Like This
{
"programs": [
],
"streams": [
{
"index": 1,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "High",
"codec_type": "video",
"codec_time_base": "299/36000",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 720,
"height": 1280,
"coded_width": 720,
"coded_height": 1280,
"has_b_frames": 1,
"pix_fmt": "yuvj420p",
"level": 32,
"color_range": "pc",
"color_space": "bt709",
"color_transfer": "bt709",
"color_primaries": "bt709",
"chroma_location": "left",
"refs": 1,
"is_avc": "true",
"nal_length_size": "4",
"r_frame_rate": "60/1",
"avg_frame_rate": "18000/299",
"time_base": "1/600",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 2093,
"duration": "3.488333",
"bit_rate": "3284683",
"bits_per_raw_sample": "8",
"nb_frames": "210",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"rotate": "270",
"creation_time": "2021-07-15T23:03:31.000000Z",
"language": "und",
"handler_name": "Core Media Video",
"encoder": "H.264"
},
"side_data_list": [
{
"side_data_type": "Display Matrix",
"displaymatrix": "\n00000000: 0 -65536 0\n00000001: 65536 0 0\n00000002: 0 83886080 1073741824\n",
"rotation": 90
}
]
}
]
}