diff options
author | bobzel <zzzman@gmail.com> | 2020-05-18 21:50:20 +0000 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2020-05-18 21:50:20 +0000 |
commit | da7ba72e8c75dfaa9920920b8234d99f699578a8 (patch) | |
tree | 2b9c30a12396b95a681f14829965190918642725 /src | |
parent | beece97c0645b1466b2c4210b594220b84953e04 (diff) |
youtube screenshot backend implemented
Diffstat (limited to 'src')
-rw-r--r-- | src/server/ApiManagers/UploadManager.ts | 64 | ||||
-rw-r--r-- | src/server/DashUploadUtils.ts | 2 |
2 files changed, 60 insertions, 6 deletions
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index b185d3b55..06c2e516d 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -4,14 +4,18 @@ import * as formidable from 'formidable'; import v4 = require('uuid/v4'); const AdmZip = require('adm-zip'); import { extname, basename, dirname } from 'path'; -import { createReadStream, createWriteStream, unlink } from "fs"; +import { createReadStream, createWriteStream, unlink, writeFile } from "fs"; import { publicDirectory, filesDirectory } from ".."; import { Database } from "../database"; import { DashUploadUtils, InjectSize, SizeSuffix } from "../DashUploadUtils"; import * as sharp from 'sharp'; import { AcceptibleMedia, Upload } from "../SharedMediaTypes"; import { normalize } from "path"; +import RouteSubscriber from "../RouteSubscriber"; const imageDataUri = require('image-data-uri'); +import { isWebUri } from "valid-url"; +import { launch } from "puppeteer"; +import { Opt } from "../../fields/Doc"; export enum Directory { parsed_files = "parsed_files", @@ -61,10 +65,38 @@ export default class UploadManager extends ApiManager { }); register({ - method: Method.GET, - subscription: "/hello", - secureHandler: ({ req, res }) => { - res.send("<h1>world!</h1>"); + method: Method.POST, + subscription: new RouteSubscriber("youtubeScreenshot"), + secureHandler: async ({ req, res }) => { + const { url, t } = req.query; + const parseUrl = (url: string) => { + url = decodeURIComponent(url) + if (!/^(?:f|ht)tps?\:\/\//.test(url)) { + url = 'http://' + url + } + return url; + } + let targetUrl: string; + if (!url || !t || !isWebUri(targetUrl = parseUrl(url as string))) { + return res.send(); + } + const buffer = await captureYoutubeScreenshot(targetUrl, t as string); + if (!buffer) { + return res.send(); + } + const resolvedName = `${targetUrl}@${t}.png`; + const resolvedPath = serverPathToFile(Directory.images, resolvedName); + writeFile(resolvedPath, buffer, async error => { + if (error) { + return res.send(); + } + await DashUploadUtils.outputResizedImages(() => createReadStream(resolvedPath), resolvedName, pathToDirectory(Directory.images)); + res.send({ + accessPaths: { + agnostic: DashUploadUtils.getAccessPaths(Directory.images, resolvedName) + } + } as Upload.FileInformation); + }); } }); @@ -244,4 +276,26 @@ export default class UploadManager extends ApiManager { } +} + +/** + * On success, returns a buffer containing the bytes of a screenshot + * of the video specified by @param url at timecode @param t. + * + * On failure, returns undefined. + */ +async function captureYoutubeScreenshot(targetUrl: string, t: string): Promise<Opt<Buffer>> { + const browser = await launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] }); + const page = await browser.newPage(); + await page.setViewport({ width: 1920, height: 1080 }); + + await page.goto(targetUrl + '&t=' + t, { waitUntil: 'networkidle0' }); + + // hide youtube player controls. + await page.evaluate(() => (document.querySelector('.ytp-chrome-bottom') as any).style.display = 'none'); + + const buffer = await (await page.$('.html5-video-player'))?.screenshot({ encoding: "binary" }); + await browser.close(); + + return buffer; }
\ No newline at end of file diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index b74904ada..c887aa4e6 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -257,7 +257,7 @@ export namespace DashUploadUtils { }); } - function getAccessPaths(directory: Directory, fileName: string) { + export function getAccessPaths(directory: Directory, fileName: string) { return { client: clientPathToFile(directory, fileName), server: serverPathToFile(directory, fileName) |