Skip to content

Instantly share code, notes, and snippets.

@fromkk
Created February 1, 2024 06:59
Show Gist options
  • Save fromkk/5eb375d6708aaa7fad868a87c43462d9 to your computer and use it in GitHub Desktop.
Save fromkk/5eb375d6708aaa7fad868a87c43462d9 to your computer and use it in GitHub Desktop.
Generate highlight movie with Transcoder API
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