Update utils.ts
This commit is contained in:
114
scripts/utils.ts
114
scripts/utils.ts
@@ -1,9 +1,13 @@
|
|||||||
import { MasterPlaylist, MediaPlaylist, Variant } from 'hls-parser/types'
|
import axios, { AxiosProxyConfig, AxiosRequestConfig } from 'axios'
|
||||||
import { parse as parsePlaylist } from 'hls-parser'
|
import { parse as parsePlaylist, setOptions } from 'hls-parser'
|
||||||
|
import { parse as parseManifest } from 'mpd-parser'
|
||||||
|
import { SocksProxyAgent } from 'socks-proxy-agent'
|
||||||
|
import { ProxyParser } from './core/proxyParser.js'
|
||||||
import { TESTING } from './constants.js'
|
import { TESTING } from './constants.js'
|
||||||
import normalizeUrl from 'normalize-url'
|
import normalizeUrl from 'normalize-url'
|
||||||
import { orderBy } from 'es-toolkit'
|
import { orderBy } from 'es-toolkit'
|
||||||
import axios from 'axios'
|
import path from 'node:path'
|
||||||
|
import fs from 'node:fs'
|
||||||
|
|
||||||
export function isURI(string: string): boolean {
|
export function isURI(string: string): boolean {
|
||||||
try {
|
try {
|
||||||
@@ -27,32 +31,110 @@ export function truncate(string: string, limit: number = 100) {
|
|||||||
return string.slice(0, limit - 3) + '...'
|
return string.slice(0, limit - 3) + '...'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StreamInfo = {
|
||||||
|
resolution: { width: number; height: number }
|
||||||
|
bandwidth: number
|
||||||
|
frameRate: number
|
||||||
|
codecs: string
|
||||||
|
}
|
||||||
|
|
||||||
export async function getStreamInfo(
|
export async function getStreamInfo(
|
||||||
url: string,
|
url: string,
|
||||||
options: { httpUserAgent: string | null; httpReferrer: string | null }
|
options: {
|
||||||
): Promise<Variant | undefined> {
|
httpUserAgent?: string | null
|
||||||
let playlist: MasterPlaylist | MediaPlaylist | undefined
|
httpReferrer?: string | null
|
||||||
|
timeout?: number
|
||||||
|
proxy?: string
|
||||||
|
}
|
||||||
|
): Promise<StreamInfo | undefined> {
|
||||||
|
let data: string | undefined
|
||||||
if (TESTING) {
|
if (TESTING) {
|
||||||
playlist = (await import('../tests/__data__/input/playlist_update/playlist.mjs'))
|
if (url.includes('.m3u8')) {
|
||||||
.default as unknown as MasterPlaylist
|
data = fs.readFileSync(
|
||||||
|
path.resolve(__dirname, '../tests/__data__/input/playlist_update/playlist.m3u8'),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
} else if (url.includes('.mpd')) {
|
||||||
|
data = fs.readFileSync(
|
||||||
|
path.resolve(__dirname, '../tests/__data__/input/playlist_update/manifest.mpd'),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const response = await axios(url, {
|
const timeout = options.timeout || 1000
|
||||||
signal: AbortSignal.timeout(30000),
|
let request: AxiosRequestConfig = {
|
||||||
|
signal: AbortSignal.timeout(timeout),
|
||||||
|
responseType: 'text',
|
||||||
headers: {
|
headers: {
|
||||||
'User-Agent': options.httpUserAgent || 'Mozilla/5.0',
|
'User-Agent': options.httpUserAgent || 'Mozilla/5.0',
|
||||||
Referer: options.httpReferrer
|
Referer: options.httpReferrer
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
playlist = parsePlaylist(response.data)
|
if (options.proxy !== undefined) {
|
||||||
|
const proxyParser = new ProxyParser()
|
||||||
|
const proxy = proxyParser.parse(options.proxy) as AxiosProxyConfig
|
||||||
|
if (
|
||||||
|
proxy.protocol &&
|
||||||
|
['socks', 'socks5', 'socks5h', 'socks4', 'socks4a'].includes(String(proxy.protocol))
|
||||||
|
) {
|
||||||
|
const socksProxyAgent = new SocksProxyAgent(options.proxy)
|
||||||
|
|
||||||
|
request = { ...request, ...{ httpAgent: socksProxyAgent, httpsAgent: socksProxyAgent } }
|
||||||
|
} else {
|
||||||
|
request = { ...request, ...{ proxy } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await axios(url, request)
|
||||||
|
|
||||||
|
data = response.data
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playlist && playlist.isMasterPlaylist && playlist.variants.length) {
|
if (!data) return undefined
|
||||||
return orderBy(playlist.variants, ['bandwidth'], ['desc'])[0]
|
|
||||||
|
let info: StreamInfo | undefined
|
||||||
|
|
||||||
|
if (url.includes('.m3u8')) {
|
||||||
|
setOptions({ silent: true })
|
||||||
|
|
||||||
|
try {
|
||||||
|
const playlist = parsePlaylist(data)
|
||||||
|
|
||||||
|
if (playlist && playlist.isMasterPlaylist && playlist.variants.length) {
|
||||||
|
const v = orderBy(playlist.variants, ['bandwidth'], ['desc'])[0]
|
||||||
|
|
||||||
|
if (v && v.resolution && v.frameRate && v.codecs) {
|
||||||
|
info = {
|
||||||
|
resolution: { width: v.resolution.width, height: v.resolution.height },
|
||||||
|
bandwidth: v.bandwidth,
|
||||||
|
frameRate: v.frameRate,
|
||||||
|
codecs: v.codecs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
} else if (url.includes('.mpd')) {
|
||||||
|
const manifest = parseManifest(data, {
|
||||||
|
manifestUri: url,
|
||||||
|
eventHandler: ({ type, message }) => console.log(`${type}: ${message}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
const playlist = orderBy(manifest.playlists, [p => p.attributes.BANDWIDTH], ['desc'])[0]
|
||||||
|
|
||||||
|
if (playlist) {
|
||||||
|
const attr = playlist.attributes
|
||||||
|
|
||||||
|
info = {
|
||||||
|
resolution: { width: attr.RESOLUTION.width, height: attr.RESOLUTION.height },
|
||||||
|
bandwidth: attr.BANDWIDTH,
|
||||||
|
frameRate: attr['FRAME-RATE'],
|
||||||
|
codecs: attr.CODECS
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined
|
return info
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user