UNPKG

scrptly

Version:

Scrptly is a Video Development Kit (VDK) for programmatically generating AI-powered videos.

95 lines (90 loc) 2.47 kB
import fs from 'fs'; import crypto from 'crypto'; import type Scrptly from './index'; export default class AssetUploader { $: Scrptly; path: string; type: string; constructor($: Scrptly, path: string, type: string) { this.$ = $; this.path = path; this.type = type; } async hashFile(): Promise<string> { return new Promise((resolve, reject) => { const hash = crypto.createHash('md5'); const stream = fs.createReadStream(this.path); stream.on('error', reject); stream.on('data', chunk => { hash.update(chunk); }); stream.on('end', () => { resolve(hash.digest('base64')); }); }); } async uploadAsset() { // Calculate hash of the file const { size } = await fs.promises.stat(this.path); const hash = await this.hashFile(); const fileName = this.path.split('/').pop(); const extension = fileName?.split('.').pop(); if(!fileName || !extension) throw new Error('Invalid file name or extension'); const prepare = await this.$.apiCall('prepareAsset', { method: 'POST', body: JSON.stringify({ fileName, hash, type: this.type, extension, size }), }); if(prepare.success) { if(prepare.found) { return {assetId: prepare.assetId, url: prepare.url}; } else if(prepare.presignedUrl) { const fileStream = fs.createReadStream(this.path); const res = await fetch(prepare.presignedUrl, { method: 'PUT', headers: { 'Content-Type': prepare.contentType, 'Content-Length': size.toString(), 'Content-MD5': hash, }, body: fileStream as any, // @ts-expect-error duplex: 'half' }); if (res.ok) { const successUpload = await this.$.apiCall('completeAssetUpload', { method: 'POST', body: JSON.stringify({ assetId: prepare.assetId, result: 'success', }), }); if(successUpload.success) { return {assetId: successUpload.assetId, url: successUpload.url}; } else { throw new Error(`Could not complete upload: ${successUpload.error}`); } } else { await this.$.apiCall('completeAssetUpload', { method: 'POST', body: JSON.stringify({ assetId: prepare.assetId, result: 'error', }), }); throw new Error(`Upload failed [${res.status}]\n> ${await res.text()}`); } } else { throw new Error('Invalid response from server'); } } else { throw new Error(`Error uploading asset: ${prepare.error}`); } } }