Bilibili-Evolved/registry/lib/components/video/subtitle/download/utils.ts
2022-10-12 23:27:58 +08:00

99 lines
3.2 KiB
TypeScript

import { getJson } from '@/core/ajax'
import { Toast } from '@/core/toast'
import { getFriendlyTitle } from '@/core/utils/title'
import { SubtitleConverterConfig } from '../subtitle-converter'
export type SubtitleDownloadType = 'json' | 'ass'
export const getSubtitleConfig = async (): Promise<[SubtitleConverterConfig, string]> => {
const { SubtitleConverter, SubtitleSize, SubtitleLocation } = await import(
'../subtitle-converter'
)
const { playerAgent } = await import('@/components/video/player-agent')
const playerSettingsText = localStorage.getItem('bilibili_player_settings')
if (!playerSettingsText) {
return [SubtitleConverter.defaultConfig, '']
}
const subtitleSettings = JSON.parse(playerSettingsText).subtitle
const language = subtitleSettings.lan
const title = getFriendlyTitle(true)
const fontSizeMapping: { [key: number]: number } = {
0.6: SubtitleSize.VerySmall,
0.8: SubtitleSize.Small,
1: SubtitleSize.Medium,
1.3: SubtitleSize.Large,
1.6: SubtitleSize.VeryLarge,
}
const size = fontSizeMapping[subtitleSettings.fontsize]
const color = subtitleSettings.color.toString(16)
const opacity = subtitleSettings.backgroundopacity
const positions = {
bc: SubtitleLocation.BottomCenter,
bl: SubtitleLocation.BottomLeft,
br: SubtitleLocation.BottomRight,
tc: SubtitleLocation.TopCenter,
tl: SubtitleLocation.TopLeft,
tr: SubtitleLocation.TopRight,
}
const subtitleLocation = positions[subtitleSettings.position]
const video = playerAgent.query.video.element.sync() as HTMLVideoElement
const config: SubtitleConverterConfig = {
title,
height: video.videoHeight,
width: video.videoWidth,
color,
location: subtitleLocation,
opacity,
size,
boxPadding: 1,
boxMargin: 32,
}
return [config, language]
}
export const getSubtitleList = async (aid: string, cid: string | number) => {
const { VideoInfo } = await import('@/components/video/video-info')
const info = new VideoInfo(aid)
info.cid = typeof cid === 'string' ? parseInt(cid) : cid
await info.fetchInfo()
return info.subtitles
}
export const getBlobByType = async (
type: SubtitleDownloadType,
input: {
aid: string
cid: string
title: string
} = { ...lodash.pick(unsafeWindow, 'aid', 'cid'), title: getFriendlyTitle(true) },
) => {
const { aid, cid } = input
if (!aid || !cid) {
throw new Error('未找到视频AID和CID')
}
const subtitles = await getSubtitleList(aid, cid)
if (subtitles.length === 0) {
Toast.info('当前视频没有字幕.', '下载字幕', 3000)
return null
}
const [config, language] = await getSubtitleConfig()
const subtitle = subtitles.find(s => s.language === language) || subtitles[0]
const json = await getJson(subtitle.url)
const rawData = json.body
switch (type) {
case 'ass': {
const { SubtitleConverter } = await import('../subtitle-converter')
const converter = new SubtitleConverter({ ...config, title: input.title })
const assText = await converter.convertToAss(rawData)
return new Blob([assText], {
type: 'text/ass',
})
}
default:
case 'json': {
return new Blob([JSON.stringify(rawData)], {
type: 'text/json',
})
}
}
}