UNPKG

@xbibzlibrary/tiktokscrap

Version:

Powerful TikTok Scraper and Downloader Library

133 lines (118 loc) 3.94 kB
import BaseDownloader from './base'; import { TikTokVideo, TikTokDownloadOptions, TikTokScrapResult } from '../types'; import path from 'path'; export class VideoDownloader extends BaseDownloader { public async downloadVideo( video: TikTokVideo, options: TikTokDownloadOptions = {} ): Promise<TikTokScrapResult<string>> { return this.executeDownload(async () => { const { outputDir = './downloads', filename } = options; if (!video.downloadAddr) { throw new Error('Video download URL not available'); } const videoFilename = this.generateFilename(video.downloadAddr, '.mp4', { filename }); const outputPath = this.getOutputPath(outputDir, videoFilename); return this.downloadFile(video.downloadAddr, outputPath, options); }, `Download video: ${video.id}`); } public async downloadVideoByUrl( url: string, options: TikTokDownloadOptions = {} ): Promise<TikTokScrapResult<string>> { return this.executeDownload(async () => { // This would require importing the VideoScraper, but to avoid circular dependencies, // we'll assume the URL is valid and extract the video ID const videoId = this.extractVideoIdFromUrl(url); if (!videoId) { throw new Error('Could not extract video ID from URL'); } // In a real implementation, you would use the VideoScraper to get the video data // For now, we'll construct a minimal video object with the URL const video: TikTokVideo = { id: videoId, text: '', createTime: 0, author: { id: '', uniqueId: '', nickname: '', avatarUrl: '', signature: '', verified: false, following: 0, fans: 0, heart: 0, video: 0, digg: 0, privateAccount: false, isSecret: false, secUid: '' }, music: { id: '', title: '', author: '', album: '', playUrl: '', coverLarge: '', coverMedium: '', coverThumb: '', duration: 0 }, stats: { digg: 0, share: 0, comment: 0, play: 0 }, videoMeta: { width: 0, height: 0, duration: 0, cover: '', dynamicCover: '', originCover: '' }, downloadAddr: url, webVideoUrl: url, hashtags: [], mentions: [], effects: [], isAd: false, commentsDisabled: false, duetEnabled: false, stitchEnabled: false, secret: false, forFriend: false, digged: false, itemCommentStatus: 0 }; const result = await this.downloadVideo(video, options); if (result.success && result.data) { return result.data; } else { throw new Error(result.error || 'Failed to download video by URL'); } }, `Download video by URL: ${url}`); } public async downloadVideoCover( video: TikTokVideo, options: TikTokDownloadOptions = {} ): Promise<TikTokScrapResult<string>> { return this.executeDownload(async () => { const { outputDir = './downloads', filename } = options; if (!video.videoMeta.cover) { throw new Error('Video cover URL not available'); } const coverFilename = this.generateFilename(video.videoMeta.cover, '.jpg', { filename }); const outputPath = this.getOutputPath(outputDir, coverFilename); return this.downloadFile(video.videoMeta.cover, outputPath, options); }, `Download video cover: ${video.id}`); } private extractVideoIdFromUrl(url: string): string | null { const match = url.match(/\/video\/(\d+)/); return match ? match[1] : null; } } export default VideoDownloader;