|
- import {
- createVideoClipper,
- YouTube,
- VideoType,
- ClipVideoParams,
- } from '@modal/webvideo-clip-core';
- import { constants } from 'http2';
- import { RouteHandlerMethod } from 'fastify';
-
- export type ClipArgs = {
- url?: unknown,
- start?: string | number,
- end?: string | number,
- }
-
- const DURATION_STRING_REGEXP = /^\d\d:[0-5]\d:[0-5]\d(\.\d+)?$/;
-
- const validateRequestBody = (body: ClipArgs) => {
- const messages = [] as string[];
- const { url, start, end } = body;
- if (typeof url !== 'string') {
- messages.push('URL is required.');
- }
-
- const typeofStart = typeof start;
- if (typeofStart !== 'undefined') {
- if (
- !['string', 'number'].includes(typeofStart)
- || (typeofStart === 'string' && !DURATION_STRING_REGEXP.test(start as string))
- ) {
- messages.push('Invalid start value.');
- }
- }
-
- const typeofEnd = typeof end;
- if (typeofEnd !== 'undefined') {
- if (
- !['string', 'number'].includes(typeofEnd)
- || (typeofEnd === 'string' && !DURATION_STRING_REGEXP.test(end as string))
- ) {
- messages.push('Invalid end value.');
- }
- }
-
- return messages;
- };
-
- const getVideoType = (url: string) => {
- if (url.startsWith('https://www.youtube.com')) {
- return YouTube.VIDEO_TYPE as VideoType;
- }
-
- return null;
- };
-
- export const clip: RouteHandlerMethod = async (request, reply) => {
- const validationMessages = validateRequestBody(request.body as ClipArgs);
- if (validationMessages.length > 0) {
- reply
- .status(constants.HTTP_STATUS_BAD_REQUEST)
- .send({
- errors: validationMessages,
- });
- return;
- }
- const videoType = getVideoType((request.body as ClipArgs).url as string);
- if (videoType === null) {
- reply
- .status(constants.HTTP_STATUS_UNPROCESSABLE_ENTITY)
- .send({
- errors: ['Unsupported URL.'],
- });
- }
-
- const clipper = createVideoClipper({
- type: videoType as VideoType,
- downloaderExecutablePath: process.env.YOUTUBE_DOWNLOADER_EXECUTABLE_PATH as string,
- });
-
- const { url, start, end } = request.body as ClipVideoParams;
- const clipResult = await clipper({
- url,
- start,
- end,
- });
-
- reply
- .header('Content-Type', clipResult.contentType)
- .send(clipResult.content);
- };
|