Skip to content

Commit

Permalink
Merge branch 'preview-features' of https://github.com/the1812/Bilibil…
Browse files Browse the repository at this point in the history
…i-Evolved into preview-features
  • Loading branch information
the1812 committed Jul 30, 2024
2 parents a866202 + fbd459d commit a1df99a
Show file tree
Hide file tree
Showing 14 changed files with 520 additions and 73 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"durl",
"epid",
"esbuild",
"ffmetadata",
"flac",
"Fullscreen",
"githubusercontent",
Expand Down
22 changes: 21 additions & 1 deletion registry/lib/components/utils/view-cover/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineComponentMetadata } from '@/components/define'
import { getBlobByAid } from '@/components/video/video-cover'
import { getVideoCoverUrlByAid, getBlobByAid } from '@/components/video/video-cover'
import { PackageEntry } from '@/core/download'
import { videoAndBangumiUrls } from '@/core/utils/urls'
import { Toast } from '@/core/toast'
Expand Down Expand Up @@ -55,6 +55,26 @@ export const component = defineComponentMetadata({
toast.message = `获取完成. 成功 ${success.length} 个, 失败 ${fail.length} 个.`
return success.map(it => it.value)
},
getUrls: async (
infos,
instance: {
type: CoverDownloadType
enabled: boolean
},
) => {
const { type, enabled } = instance
if (!enabled) {
return []
}
return Promise.all(
infos.map(async info => {
return {
name: `${info.input.title}.${type}`,
url: await getVideoCoverUrlByAid(info.input.aid),
}
}),
)
},
component: () => import('./Plugin.vue').then(m => m.default),
})
})
Expand Down
20 changes: 8 additions & 12 deletions registry/lib/components/video/download/DownloadVideo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -330,19 +330,15 @@ export default Vue.extend({
})
}
const action = new DownloadVideoAction(videoInfos)
const extraAssets = (
await Promise.all(
assets.map(a =>
a.getAssets(
videoInfos,
this.$refs.assetsOptions.find((c: any) => c.$attrs.name === a.name),
),
),
)
).flat()
action.extraAssets.push(...extraAssets)
await action.downloadExtraAssets()
assets.forEach(a => {
const assetsType = a?.getUrls ? action.extraOnlineAssets : action.extraAssets
assetsType.push({
asset: a,
instance: this.$refs.assetsOptions.find((c: any) => c.$attrs.name === a.name),
})
})
await output.runAction(action, instance)
await action.downloadExtraAssets()
} catch (error) {
logError(error)
} finally {
Expand Down
22 changes: 19 additions & 3 deletions registry/lib/components/video/download/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,19 @@ export interface DownloadVideoApi extends WithName {
/** 表示下载时额外附带的产物, 如弹幕 / 字幕等 */
export interface DownloadVideoAssets<AssetsParameter = any> extends VueInstanceInput, WithName {
getAssets: (infos: DownloadVideoInfo[], instance: AssetsParameter) => Promise<PackageEntry[]>
/** 获取可直接下载的链接 */
getUrls?: (
infos: DownloadVideoInfo[],
instance: AssetsParameter,
) => Promise<{ name: string; url: string }[]>
}
/** 表示视频的下载信息以及携带的额外产物 */
export class DownloadVideoAction {
export class DownloadVideoAction<AssetsParameter = any> {
readonly inputs: DownloadVideoInputItem[] = []
extraAssets: PackageEntry[] = []
/** 可调用处理的asset和对应的参数 */
extraAssets: { asset: DownloadVideoAssets; instance: AssetsParameter }[] = []
/** 可直接下载的asset和对应的参数 */
extraOnlineAssets: { asset: DownloadVideoAssets; instance: AssetsParameter }[] = []

constructor(public infos: DownloadVideoInfo[]) {
this.inputs = infos.map(it => it.input)
Expand All @@ -92,7 +100,15 @@ export class DownloadVideoAction {
async downloadExtraAssets() {
console.log('[downloadExtraAssets]', this.extraAssets)
const filename = `${getFriendlyTitle(false)}.zip`
await new DownloadPackage(this.extraAssets).emit(filename)
const { infos } = this
const extraAssetsBlob = (
await Promise.all(
[...this.extraAssets, ...this.extraOnlineAssets].map(({ asset, instance }) =>
asset.getAssets(infos, instance),
),
)
).flat()
await new DownloadPackage(extraAssetsBlob).emit(filename)
}
}
/** 下载视频的最终输出处理 */
Expand Down
44 changes: 44 additions & 0 deletions registry/lib/components/video/metadata/Plugin.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<template>
<div class="download-video-config-section">
<div class="download-video-config-item">
<div>元数据:</div>
<VDropdown v-model="type" :items="items">
<template #item="{ item }">
{{ item }}
</template>
</VDropdown>
</div>
</div>
</template>
<script lang="ts">
import { VDropdown } from '@/ui'
import { getComponentSettings } from '@/core/settings'
import { MetadataType } from './metadata'
interface Options {
metadataType: MetadataType | ''
}
const options = getComponentSettings('downloadVideo').options as Options
export default Vue.extend({
components: {
VDropdown,
},
data() {
return {
type: options.metadataType ?? '',
items: ['', 'ffmetadata', 'ogm'],
}
},
computed: {
enabled() {
return this.type !== ''
},
},
watch: {
type(value: MetadataType) {
options.metadataType = value
},
},
})
</script>
48 changes: 48 additions & 0 deletions registry/lib/components/video/metadata/SaveMetadata.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<div class="multiple-widgets">
<DefaultWidget
ref="button"
:disabled="disabled"
name="保存视频元数据"
icon="mdi-download"
@click="run('ffmetadata')"
></DefaultWidget>
<DefaultWidget
:disabled="disabled"
name="保存视频章节"
icon="mdi-download"
@click="run('ogm')"
></DefaultWidget>
</div>
</template>

<script lang="ts">
import { DefaultWidget } from '@/ui'
import { logError } from '@/core/utils/log'
import { DownloadPackage } from '@/core/download'
import { getFriendlyTitle } from '@/core/utils/title'
import { MetadataType, generateByType } from './metadata'
export default Vue.extend({
components: {
DefaultWidget,
},
data() {
return {
disabled: false,
}
},
methods: {
async run(type: MetadataType) {
try {
this.disabled = true
DownloadPackage.single(`${getFriendlyTitle(true)}.${type}.txt`, await generateByType(type))
} catch (error) {
logError(error)
} finally {
this.disabled = false
}
},
},
})
</script>
72 changes: 72 additions & 0 deletions registry/lib/components/video/metadata/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { defineComponentMetadata } from '@/components/define'
import { PackageEntry } from '@/core/download'
import { hasVideo } from '@/core/spin-query'
import { Toast } from '@/core/toast'
import { videoUrls } from '@/core/utils/urls'
import { DownloadVideoAssets } from '../download/types'
import { generateByType, MetadataType } from './metadata'

export const title = '保存视频元数据'
export const name = 'saveVideoMetadata'

const author = [
{
name: 'WakelessSloth56',
link: 'https://github.com/WakelessSloth56',
},
{
name: 'LainIO24',
link: 'https://github.com/LainIO24',
},
]

export const component = defineComponentMetadata({
name,
displayName: title,
description: '保存视频元数据(标题、描述、UP、章节等)',
author,
tags: [componentsTags.video],
entry: none,
urlInclude: videoUrls,
widget: {
condition: hasVideo,
component: () => import('./SaveMetadata.vue').then(m => m.default),
},
plugin: {
displayName: `下载视频 - ${title}支持`,
author,
setup: ({ addData }) => {
addData('downloadVideo.assets', async (assets: DownloadVideoAssets[]) => {
assets.push({
name,
displayName: title,
getAssets: async (
infos,
instance: {
type: MetadataType
enabled: boolean
},
) => {
const { type, enabled } = instance
if (enabled) {
const toast = Toast.info('获取视频元数据中...', title)
const result: PackageEntry[] = []
for (const info of infos) {
result.push({
name: `${info.input.title}.${type}.txt`,
data: await generateByType(type, info.input.aid, info.input.cid),
options: {},
})
}
toast.message = '完成!'
toast.duration = 1000
return result
}
return []
},
component: () => import('./Plugin.vue').then(m => m.default),
})
})
},
},
})
Loading

0 comments on commit a1df99a

Please sign in to comment.