Created
February 1, 2024 06:59
-
-
Save fromkk/5eb375d6708aaa7fad868a87c43462d9 to your computer and use it in GitHub Desktop.
Generate highlight movie with Transcoder API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const projectId = "your-project-id"; | |
const location = "asia-east1"; | |
const {TranscoderServiceClient} = require("@google-cloud/video-transcoder").v1; | |
const client = new TranscoderServiceClient(); | |
/** | |
* calcOffsetNanoSec | |
* @param {number} offsetValueFractionalSecs input | |
* @return {number} | |
*/ | |
function calcOffsetNanoSec(offsetValueFractionalSecs) { | |
if (offsetValueFractionalSecs.toString().indexOf(".") !== -1) { | |
return ( | |
1000000000 * | |
Number("." + offsetValueFractionalSecs.toString().split(".")[1]) | |
); | |
} | |
return 0; | |
} | |
/** @typedef {{start: number, end: number}} startAndEndResult */ | |
/** | |
* get start and end from duration and minimum length. | |
* @param {number} duration | |
* @param {number} minimumLength | |
* @return {startAndEndResult} | |
*/ | |
function startAndEnd(duration, minimumLength) { | |
if (duration > minimumLength) { | |
const halfDuration = duration / 2; | |
const halfMinimumLength = minimumLength / 2; | |
return { | |
"start": halfDuration - halfMinimumLength, | |
"end": halfDuration + halfMinimumLength - 0.01, | |
}; | |
} else { | |
return { | |
"start": 0, "end": duration - 0.01, | |
}; | |
} | |
} | |
/** | |
* @typedef {{input: string, start: number, end: number}} resource | |
*/ | |
/** | |
* create job | |
* @param {resource[]} resources inputs | |
* @param {string} output url | |
*/ | |
async function createJob(resources, output) { | |
const inputs = resources.map((resource, index) => { | |
return { | |
key: `input${index + 1}`, | |
uri: resource.input, | |
}; | |
}); | |
const editList = resources.map((resource, index) => { | |
const startTimeOffsetSec = Math.trunc(resource.start); | |
const startTimeOffsetNanoSec = calcOffsetNanoSec(resource.start); | |
const endTimeOffsetSec = Math.trunc(resource.end); | |
const endTimeOffsetNanoSec = calcOffsetNanoSec(resource.end); | |
return { | |
key: `atom${index + 1}`, | |
inputs: [`input${index + 1}`], | |
startTimeOffset: { | |
seconds: startTimeOffsetSec, | |
nanos: startTimeOffsetNanoSec, | |
}, | |
endTimeOffset: { | |
seconds: endTimeOffsetSec, | |
nanos: endTimeOffsetNanoSec, | |
}, | |
}; | |
}); | |
const request = { | |
parent: client.locationPath(projectId, location), | |
job: { | |
outputUri: output, | |
config: { | |
inputs: inputs, | |
editList: editList, | |
elementaryStreams: [ | |
{ | |
key: "video-stream0", | |
videoStream: { | |
h264: { | |
heightPixels: 1024, | |
widthPixels: 1024, | |
bitrateBps: 1100000, | |
frameRate: 30, | |
}, | |
}, | |
}, | |
{ | |
key: "audio-stream0", | |
audioStream: { | |
codec: "aac", | |
bitrateBps: 64000, | |
}, | |
}, | |
], | |
muxStreams: [ | |
{ | |
key: "hd", | |
container: "mp4", | |
elementaryStreams: ["video-stream0", "audio-stream0"], | |
}, | |
], | |
}, | |
}, | |
}; | |
// Run request | |
const [response] = await client.createJob(request); | |
console.log(`Job: ${response.name}`); | |
} | |
function main() async { | |
const contents = await getYourContents(); | |
/** @type {resource[]} */ | |
const resources = contents.map((content) => { | |
/** @type {number} */ | |
const duration = startAndEnd(content.duration, 1); | |
return { | |
"input": `gs://your-project.appspot.com/${content.path}`, | |
"start": duration.start, | |
"end": duration.end, | |
}; | |
}); | |
const outputUrl = `gs://your-project.appspot.com/highlight/`; | |
await createJob(resources, outputUrl); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment