Bilibili-Evolved/registry/lib/components/video/metadata/metadata.ts
WakelessSloth56 7d5286d30a
feat: component saveVideoMetadata more fields
author, category_id, category_name, publish_date

Co-authored-by: lainio24 <lainio24@outlook.com>
2024-07-22 19:44:46 +08:00

116 lines
2.9 KiB
TypeScript

import { VideoInfo, VideoPageInfo } from '@/components/video/video-info'
import { VideoQuality } from '@/components/video/video-quality'
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
import { meta } from '@/core/meta'
function escape(s: string) {
return s.replace(/[=;#\\\n]/g, r => `\\${r}`)
}
function ff(key: string, value: any, prefix = true) {
return `${prefix ? 'bilibili_' : ''}${key}=${escape(lodash.toString(value))}`
}
export interface ViewPoint {
content: string
from: number
to: number
image: string
}
export class VideoMetadata {
#aid: string
#cid: number | string
basic: VideoInfo
viewPoints: ViewPoint[]
page: VideoPageInfo
quality?: VideoQuality
constructor(aid: string, cid: number | string) {
this.#aid = aid
this.#cid = cid
this.basic = new VideoInfo(aid)
}
async fetch() {
await this.basic.fetchInfo()
this.page = this.basic.pages.filter(p => p.cid === parseInt(<any>this.#cid))[0]
const playInfo = await bilibiliApi(
getJsonWithCredentials(
`https://api.bilibili.com/x/player/wbi/v2?aid=${this.#aid}&cid=${this.#cid}`,
),
)
this.viewPoints = lodash.get(playInfo, 'view_points', []) as ViewPoint[]
}
}
export async function generateFFMetadata(
aid: string = unsafeWindow.aid,
cid: string = unsafeWindow.cid,
) {
const data = new VideoMetadata(aid, cid)
await data.fetch()
const info = data.basic
const lines = [
';FFMETADATA1',
`;generated by Bilibili-Evolved v${meta.compilationInfo.version}`,
`;generated on ${new Date().toLocaleString()}`,
// Standard fields
ff('title', `${info.title} - ${data.page.title}`, false),
ff('description', info.description, false),
ff('author', info.up.name, false),
// Custom fields
ff('title', info.title),
ff('description', info.description),
ff('publish_date', new Date(info.pubdate * 1000).toLocaleString()),
ff('aid', info.aid),
ff('bvid', info.bvid),
ff('cid', data.page.cid),
ff('category_id', info.tagId),
ff('category_name', info.tagName),
ff('page_title', data.page.title),
ff('page', data.page.pageNumber),
ff('pages', info.pages.length),
ff('up_name', info.up.name),
ff('up_uid', info.up.uid),
]
if (data.quality) {
lines.push(ff('quality', data.quality.value))
lines.push(ff('quality_label', data.quality.name))
}
if (data.viewPoints) {
for (const chapter of data.viewPoints) {
lines.push(
...[
'[CHAPTER]',
'TIMEBASE=1/1',
ff('START', chapter.from, false),
ff('END', chapter.to, false),
ff('title', chapter.content, false),
],
)
}
}
const result = lines.join('\n')
console.debug(result)
return result
}
export async function generateFFMetadataBlob(
aid: string = unsafeWindow.aid,
cid: string = unsafeWindow.cid,
) {
return new Blob([await generateFFMetadata(aid, cid)], {
type: 'text/plain',
})
}