@@ -1,4 +1,4 @@ | |||
import * as childProcess from 'child_process'; | |||
import { spawnSync } from 'child_process'; | |||
import { unlinkSync, readFileSync } from 'fs'; | |||
export enum VideoType { | |||
@@ -9,7 +9,6 @@ interface ClipVideoBaseParams { | |||
url: string, | |||
start: number | string, | |||
end: number | string, | |||
ffmpegExecutablePath?: string; | |||
} | |||
interface ClipYouTubeVideoParams extends ClipVideoBaseParams { | |||
@@ -24,12 +23,16 @@ const clipYouTubeVideo = (params: ClipYouTubeVideoParams) => { | |||
if (!params.downloaderExecutablePath) { | |||
throw new Error('Downloader not found.'); | |||
} | |||
if (!params.ffmpegExecutablePath) { | |||
throw new Error('ffmpeg not found.'); | |||
} | |||
childProcess.spawnSync(params.downloaderExecutablePath, [params.url, '-o', 'input.webm']); | |||
childProcess.spawnSync(params.ffmpegExecutablePath, ['-ss', params.start.toString(), '-t', params.end.toString(), '-i', 'input.webm', 'output.webm']); | |||
unlinkSync('input.webm'); | |||
spawnSync( | |||
params.downloaderExecutablePath, | |||
[ | |||
'--postprocessor-args', | |||
`-ss ${params.start.toString()} -to ${params.end.toString()}`, | |||
'-o', | |||
'output.webm', | |||
params.url, | |||
], | |||
); | |||
const output = readFileSync('output.webm'); | |||
unlinkSync('output.webm'); | |||
return output; | |||
@@ -38,13 +41,13 @@ const clipYouTubeVideo = (params: ClipYouTubeVideoParams) => { | |||
export const clipVideo = (params: ClipVideoParams) => { | |||
const { | |||
type: videoType, url, start, end, | |||
downloaderExecutablePath, | |||
} = params; | |||
switch (videoType as string) { | |||
case VideoType.YOUTUBE: | |||
return clipYouTubeVideo({ | |||
ffmpegExecutablePath: process.env.FFMPEG_EXECUTABLE_PATH, | |||
downloaderExecutablePath: process.env.YOUTUBE_DOWNLOADER_EXECUTABLE_PATH, | |||
downloaderExecutablePath, | |||
url, | |||
start, | |||
end, | |||
@@ -1,22 +1,57 @@ | |||
import { | |||
describe, it, expect, vi, | |||
describe, it, expect, vi, beforeEach, Mock, | |||
} from 'vitest'; | |||
import * as childProcess from 'child_process'; | |||
import { spawnSync } from 'child_process'; | |||
import { readFileSync, unlinkSync } from 'fs'; | |||
import * as youtubeClipCore from '../src'; | |||
vi.mock('child_process', () => ({ | |||
spawnSync: vi.fn(), | |||
})); | |||
vi.mock('fs', () => ({ | |||
readFileSync: vi.fn(), | |||
unlinkSync: vi.fn(), | |||
})); | |||
describe('clipVideo', () => { | |||
it('works', () => { | |||
beforeEach(() => { | |||
(readFileSync as Mock).mockReturnValueOnce(Buffer.from('')); | |||
}); | |||
it('calls the downloader function', () => { | |||
youtubeClipCore.clipVideo({ | |||
downloaderExecutablePath: 'yt-dlp', | |||
type: youtubeClipCore.VideoType.YOUTUBE, | |||
url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | |||
start: 0, | |||
end: 0, | |||
}); | |||
expect(spawnSync).toBeCalledWith('yt-dlp', expect.anything()); | |||
}); | |||
it('calls the buffer extract function', () => { | |||
youtubeClipCore.clipVideo({ | |||
downloaderExecutablePath: 'yt-dlp', | |||
type: youtubeClipCore.VideoType.YOUTUBE, | |||
url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | |||
start: 0, | |||
end: 0, | |||
}); | |||
expect(readFileSync).toBeCalled(); | |||
}); | |||
it('calls the cleanup function', () => { | |||
youtubeClipCore.clipVideo({ | |||
downloaderExecutablePath: 'yt-dlp', | |||
type: youtubeClipCore.VideoType.YOUTUBE, | |||
url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | |||
start: 0, | |||
end: 0, | |||
}); | |||
expect(childProcess.spawnSync).toBeCalledTimes(2); | |||
expect(unlinkSync).toBeCalled(); | |||
}); | |||
}); |
@@ -1,7 +1,11 @@ | |||
const { clipVideo, VideoType } = require('../dist/cjs/development'); | |||
const fs = require('fs'); | |||
const dotenv = require('dotenv'); | |||
dotenv.config(); | |||
const clippedVideoBuffer = clipVideo({ | |||
downloaderExecutablePath: process.env.YOUTUBE_DOWNLOADER_EXECUTABLE_PATH, | |||
type: VideoType.YOUTUBE, | |||
url: 'https://www.youtube.com/watch?v=BaW_jenozKc', | |||
start: 0, | |||