mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Merge branch 'preview-fixes' into preview-features
This commit is contained in:
commit
4a1417b082
17
registry/dist/components/video/download.js
vendored
17
registry/dist/components/video/download.js
vendored
File diff suppressed because one or more lines are too long
@ -144,7 +144,7 @@ import {
|
|||||||
videoDashAvc,
|
videoDashAvc,
|
||||||
videoDashHevc,
|
videoDashHevc,
|
||||||
videoDashAv1,
|
videoDashAv1,
|
||||||
audioDash,
|
videoAudioDash,
|
||||||
} from './apis/dash'
|
} from './apis/dash'
|
||||||
import { videoFlv } from './apis/flv'
|
import { videoFlv } from './apis/flv'
|
||||||
import { toastOutput } from './outputs/toast'
|
import { toastOutput } from './outputs/toast'
|
||||||
@ -170,7 +170,7 @@ const [apis] = registerAndGetData(
|
|||||||
videoDashAvc,
|
videoDashAvc,
|
||||||
videoDashHevc,
|
videoDashHevc,
|
||||||
videoDashAv1,
|
videoDashAv1,
|
||||||
audioDash,
|
videoAudioDash,
|
||||||
] as DownloadVideoApi[],
|
] as DownloadVideoApi[],
|
||||||
)
|
)
|
||||||
const [assets] = registerAndGetData(
|
const [assets] = registerAndGetData(
|
||||||
@ -188,7 +188,7 @@ const { basicConfig } = getComponentSettings('downloadVideo').options as {
|
|||||||
output: string
|
output: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const filterData = (items: { match?: TestPattern }[]) => {
|
const filterData = <T extends { match?: TestPattern }> (items: T[]) => {
|
||||||
const matchedItems = items.filter(it => it.match?.some(p => matchUrlPattern(p)) ?? true)
|
const matchedItems = items.filter(it => it.match?.some(p => matchUrlPattern(p)) ?? true)
|
||||||
return matchedItems
|
return matchedItems
|
||||||
}
|
}
|
||||||
@ -208,7 +208,6 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const lastApi = basicConfig.api
|
|
||||||
const lastOutput = basicConfig.output
|
const lastOutput = basicConfig.output
|
||||||
return {
|
return {
|
||||||
open: false,
|
open: false,
|
||||||
@ -225,8 +224,8 @@ export default Vue.extend({
|
|||||||
selectedQuality: undefined,
|
selectedQuality: undefined,
|
||||||
inputs: [],
|
inputs: [],
|
||||||
selectedInput: undefined,
|
selectedInput: undefined,
|
||||||
apis,
|
apis: [],
|
||||||
selectedApi: apis.find(it => it.name === lastApi) || apis[0],
|
selectedApi: undefined,
|
||||||
outputs,
|
outputs,
|
||||||
selectedOutput: outputs.find(it => it.name === lastOutput) || outputs[0],
|
selectedOutput: outputs.find(it => it.name === lastOutput) || outputs[0],
|
||||||
}
|
}
|
||||||
@ -278,6 +277,14 @@ export default Vue.extend({
|
|||||||
const matchedInputs = filterData(inputs)
|
const matchedInputs = filterData(inputs)
|
||||||
this.inputs = matchedInputs
|
this.inputs = matchedInputs
|
||||||
this.selectedInput = matchedInputs[0]
|
this.selectedInput = matchedInputs[0]
|
||||||
|
const matchedApis = filterData(apis)
|
||||||
|
this.apis = matchedApis
|
||||||
|
const lastApi = matchedApis.find(api => api.name === basicConfig.api)
|
||||||
|
if (lastApi) {
|
||||||
|
this.selectedApi = lastApi
|
||||||
|
} else {
|
||||||
|
this.selectedApi = matchedApis[0]
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -297,7 +304,7 @@ export default Vue.extend({
|
|||||||
return videoItems
|
return videoItems
|
||||||
},
|
},
|
||||||
async updateTestVideoInfo() {
|
async updateTestVideoInfo() {
|
||||||
if (!this.selectedInput) {
|
if (!this.selectedInput || !this.selectedApi) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.testData.videoInfo = null
|
this.testData.videoInfo = null
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
||||||
import { formData } from '@/core/utils'
|
import { formData, matchUrlPattern } from '@/core/utils'
|
||||||
import { ascendingSort, descendingSort } from '@/core/utils/sort'
|
import { ascendingSort, descendingSort } from '@/core/utils/sort'
|
||||||
import { allQualities, VideoQuality } from '@/components/video/video-quality'
|
import { allQualities, VideoQuality } from '@/components/video/video-quality'
|
||||||
|
import { bangumiUrls } from '@/core/utils/urls'
|
||||||
import { compareQuality } from '../error'
|
import { compareQuality } from '../error'
|
||||||
import {
|
import {
|
||||||
DownloadVideoApi, DownloadVideoFragment, DownloadVideoInfo, DownloadVideoInputItem,
|
DownloadVideoApi, DownloadVideoFragment, DownloadVideoInfo, DownloadVideoInputItem,
|
||||||
} from '../types'
|
} from '../types'
|
||||||
|
import { bangumiApi, videoApi } from './url'
|
||||||
/* spell-checker: disable */
|
|
||||||
|
|
||||||
/** dash 格式更明确的扩展名 */
|
/** dash 格式更明确的扩展名 */
|
||||||
export const DashExtensions = {
|
export const DashExtensions = {
|
||||||
@ -79,12 +79,14 @@ export const dashToFragments = (info: {
|
|||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* spell-checker: disable */
|
||||||
const downloadDash = async (
|
const downloadDash = async (
|
||||||
input: DownloadVideoInputItem,
|
input: DownloadVideoInputItem,
|
||||||
config: {
|
config: {
|
||||||
codec?: DashCodec
|
codec?: DashCodec
|
||||||
filters?: DashFilters
|
filters?: DashFilters
|
||||||
},
|
} = {},
|
||||||
) => {
|
) => {
|
||||||
const { codec = DashCodec.Avc, filters } = config
|
const { codec = DashCodec.Avc, filters } = config
|
||||||
const dashFilters = {
|
const dashFilters = {
|
||||||
@ -102,7 +104,8 @@ const downloadDash = async (
|
|||||||
fnver: 0,
|
fnver: 0,
|
||||||
fnval: 4048,
|
fnval: 4048,
|
||||||
}
|
}
|
||||||
const api = `https://api.bilibili.com/x/player/playurl?${formData(params)}`
|
const isBanugmi = bangumiUrls.some(url => matchUrlPattern(url))
|
||||||
|
const api = isBanugmi ? bangumiApi(formData(params)) : videoApi(formData(params))
|
||||||
const data = await bilibiliApi(
|
const data = await bilibiliApi(
|
||||||
getJsonWithCredentials(api),
|
getJsonWithCredentials(api),
|
||||||
'获取视频链接失败',
|
'获取视频链接失败',
|
||||||
@ -208,7 +211,7 @@ export const videoDashAv1: DownloadVideoApi = {
|
|||||||
description: '音画分离的 mp4 格式, 编码为 AV1, 体积较小, 兼容性较差. 下载后可以合并为单个 mp4 文件.',
|
description: '音画分离的 mp4 格式, 编码为 AV1, 体积较小, 兼容性较差. 下载后可以合并为单个 mp4 文件.',
|
||||||
downloadVideoInfo: async input => downloadDash(input, { codec: DashCodec.Av1 }),
|
downloadVideoInfo: async input => downloadDash(input, { codec: DashCodec.Av1 }),
|
||||||
}
|
}
|
||||||
export const audioDash: DownloadVideoApi = {
|
export const videoAudioDash: DownloadVideoApi = {
|
||||||
name: 'video.dash.audio',
|
name: 'video.dash.audio',
|
||||||
displayName: 'dash (仅音频)',
|
displayName: 'dash (仅音频)',
|
||||||
description: '仅下载视频中的音频轨道.',
|
description: '仅下载视频中的音频轨道.',
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
import { bilibiliApi, getJsonWithCredentials } from '@/core/ajax'
|
||||||
import { formData } from '@/core/utils'
|
import { formData, matchUrlPattern } from '@/core/utils'
|
||||||
import { allQualities } from '@/components/video/video-quality'
|
import { allQualities } from '@/components/video/video-quality'
|
||||||
|
import { bangumiUrls } from '@/core/utils/urls'
|
||||||
import { compareQuality } from '../error'
|
import { compareQuality } from '../error'
|
||||||
import {
|
import {
|
||||||
DownloadVideoApi,
|
DownloadVideoApi,
|
||||||
DownloadVideoFragment,
|
DownloadVideoFragment,
|
||||||
DownloadVideoInfo,
|
DownloadVideoInfo,
|
||||||
|
DownloadVideoInputItem,
|
||||||
} from '../types'
|
} from '../types'
|
||||||
|
import { bangumiApi, videoApi } from './url'
|
||||||
|
|
||||||
const parseInfoFromJson = (data: any, extensions: string[]) => {
|
const parseInfoFromJson = (data: any, extensions: string[]) => {
|
||||||
const getExtension = (index: number) => {
|
const getExtension = (index: number) => {
|
||||||
@ -32,33 +35,39 @@ const parseInfoFromJson = (data: any, extensions: string[]) => {
|
|||||||
currentQuality,
|
currentQuality,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* spell-checker: disable */
|
/* spell-checker: disable */
|
||||||
|
const downloadFlv = async (
|
||||||
|
input: DownloadVideoInputItem,
|
||||||
|
) => {
|
||||||
|
const { aid, cid, quality } = input
|
||||||
|
const params = {
|
||||||
|
avid: aid,
|
||||||
|
cid,
|
||||||
|
qn: quality?.value ?? '',
|
||||||
|
otype: 'json',
|
||||||
|
fourk: 1,
|
||||||
|
fnver: 0,
|
||||||
|
fnval: 0,
|
||||||
|
}
|
||||||
|
const isBanugmi = bangumiUrls.some(url => matchUrlPattern(url))
|
||||||
|
const api = isBanugmi ? bangumiApi(formData(params)) : videoApi(formData(params))
|
||||||
|
const data = await bilibiliApi(
|
||||||
|
getJsonWithCredentials(api),
|
||||||
|
'获取视频链接失败',
|
||||||
|
)
|
||||||
|
const info = new DownloadVideoInfo({
|
||||||
|
input,
|
||||||
|
jsonData: data,
|
||||||
|
...parseInfoFromJson(data, ['.flv']),
|
||||||
|
})
|
||||||
|
compareQuality(input, info)
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
export const videoFlv: DownloadVideoApi = {
|
export const videoFlv: DownloadVideoApi = {
|
||||||
name: 'video.flv',
|
name: 'video.flv',
|
||||||
displayName: 'flv',
|
displayName: 'flv',
|
||||||
description: '使用 flv 格式下载, 兼容 H.264 编码.',
|
description: '使用 flv 格式下载, 兼容 H.264 编码.',
|
||||||
downloadVideoInfo: async input => {
|
downloadVideoInfo: input => downloadFlv(input),
|
||||||
const { aid, cid, quality } = input
|
|
||||||
const params = {
|
|
||||||
avid: aid,
|
|
||||||
cid,
|
|
||||||
qn: quality?.value ?? '',
|
|
||||||
otype: 'json',
|
|
||||||
fourk: 1,
|
|
||||||
fnver: 0,
|
|
||||||
fnval: 0,
|
|
||||||
}
|
|
||||||
const api = `https://api.bilibili.com/x/player/playurl?${formData(params)}`
|
|
||||||
const data = await bilibiliApi(
|
|
||||||
getJsonWithCredentials(api),
|
|
||||||
'获取视频链接失败',
|
|
||||||
)
|
|
||||||
const info = new DownloadVideoInfo({
|
|
||||||
input,
|
|
||||||
jsonData: data,
|
|
||||||
...parseInfoFromJson(data, ['.flv']),
|
|
||||||
})
|
|
||||||
compareQuality(input, info)
|
|
||||||
return info
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|||||||
2
registry/lib/components/video/download/apis/url.ts
Normal file
2
registry/lib/components/video/download/apis/url.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const videoApi = (params: string) => `https://api.bilibili.com/x/player/playurl?${params}`
|
||||||
|
export const bangumiApi = (params: string) => `https://api.bilibili.com/pgc/player/web/playurl?${params}`
|
||||||
@ -72,6 +72,8 @@ export class DownloadVideoInfo {
|
|||||||
export interface DownloadVideoApi extends WithName {
|
export interface DownloadVideoApi extends WithName {
|
||||||
downloadVideoInfo: (input: DownloadVideoInputItem) => Promise<DownloadVideoInfo>
|
downloadVideoInfo: (input: DownloadVideoInputItem) => Promise<DownloadVideoInfo>
|
||||||
description?: string
|
description?: string
|
||||||
|
/** 网址匹配规则 */
|
||||||
|
match?: TestPattern
|
||||||
}
|
}
|
||||||
/** 表示下载时额外附带的产物, 如弹幕 / 字幕等 */
|
/** 表示下载时额外附带的产物, 如弹幕 / 字幕等 */
|
||||||
export interface DownloadVideoAssets<AssetsParameter = any> extends VueInstanceInput, WithName {
|
export interface DownloadVideoAssets<AssetsParameter = any> extends VueInstanceInput, WithName {
|
||||||
|
|||||||
@ -88,6 +88,11 @@ export async function getWatchlaterList(): Promise<number[]>
|
|||||||
export async function getWatchlaterList(raw: true): Promise<RawWatchlaterItem[]>
|
export async function getWatchlaterList(raw: true): Promise<RawWatchlaterItem[]>
|
||||||
export async function getWatchlaterList(raw: false): Promise<number[]>
|
export async function getWatchlaterList(raw: false): Promise<number[]>
|
||||||
export async function getWatchlaterList(raw = false): Promise<number[] | RawWatchlaterItem[]> {
|
export async function getWatchlaterList(raw = false): Promise<number[] | RawWatchlaterItem[]> {
|
||||||
|
const { getUID } = await import('@/core/utils')
|
||||||
|
if (!getUID()) {
|
||||||
|
console.warn('[稍后再看列表] 账号未登录')
|
||||||
|
return []
|
||||||
|
}
|
||||||
const api = 'https://api.bilibili.com/x/v2/history/toview/web'
|
const api = 'https://api.bilibili.com/x/v2/history/toview/web'
|
||||||
const { getJsonWithCredentials } = await import('@/core/ajax')
|
const { getJsonWithCredentials } = await import('@/core/ajax')
|
||||||
const response = await getJsonWithCredentials(api)
|
const response = await getJsonWithCredentials(api)
|
||||||
|
|||||||
@ -234,6 +234,7 @@ export interface BilibiliApiResponse {
|
|||||||
msg?: string
|
msg?: string
|
||||||
ttl: number
|
ttl: number
|
||||||
data: any
|
data: any
|
||||||
|
result?: any
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 进行 bilibili API 标准响应处理
|
* 进行 bilibili API 标准响应处理
|
||||||
@ -252,5 +253,5 @@ export const bilibiliApi = async <T = any>(
|
|||||||
logError(error)
|
logError(error)
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
return (json.data || {}) as T
|
return (json.data || json.result || {}) as T
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user