Skip to content

Commit 97587f3

Browse files
authored
perf(media-provider): select best format in linear time (microlinkhq#819)
1 parent db184af commit 97587f3

File tree

2 files changed

+79
-18
lines changed

2 files changed

+79
-18
lines changed

packages/metascraper-media-provider/src/index.js

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
'use strict'
22

3-
const {
4-
chain,
5-
eq,
6-
find,
7-
get,
8-
isEmpty,
9-
isNil,
10-
negate,
11-
overEvery
12-
} = require('lodash')
3+
const { eq, find, get, isEmpty, isNil, negate } = require('lodash')
134

145
const {
156
extension: extensionFn,
@@ -67,6 +58,26 @@ const hasVideo = format =>
6758
const isDownloadable = ({ url }) =>
6859
new URL(url).searchParams.get('download') === '1'
6960

61+
const getOrderByRank = value => {
62+
if (Number.isNaN(value)) return 4
63+
if (value === undefined) return 3
64+
if (value === null) return 2
65+
return 1
66+
}
67+
68+
const compareOrderByAsc = (left, right) => {
69+
const leftRank = getOrderByRank(left)
70+
const rightRank = getOrderByRank(right)
71+
72+
if (leftRank !== rightRank) return leftRank - rightRank
73+
74+
if (leftRank !== 1) return 0
75+
76+
if (left > right) return 1
77+
if (left < right) return -1
78+
return 0
79+
}
80+
7081
const getFormatUrls =
7182
(basicFilters, { orderBy }) =>
7283
(input, extraFilters, { isStream }) => {
@@ -75,14 +86,33 @@ const getFormatUrls =
7586
const formats = get(input, 'formats') ||
7687
get(input, 'entries[0].formats') || [input]
7788

78-
const url = chain(formats)
79-
.filter(overEvery(filters))
80-
.orderBy(orderBy, 'asc')
81-
.map(isStream ? 'manifest_url' : 'url')
82-
.last()
83-
.value()
84-
85-
return !isEmpty(url) ? url : undefined
89+
const urlProp = isStream ? 'manifest_url' : 'url'
90+
let lastUrl
91+
let lastOrderByValue
92+
let hasLast = false
93+
94+
for (const format of formats) {
95+
let isMatch = true
96+
for (const filter of filters) {
97+
if (!filter(format)) {
98+
isMatch = false
99+
break
100+
}
101+
}
102+
if (!isMatch) continue
103+
104+
const currentOrderByValue = format?.[orderBy]
105+
if (
106+
!hasLast ||
107+
compareOrderByAsc(currentOrderByValue, lastOrderByValue) >= 0
108+
) {
109+
lastUrl = format?.[urlProp]
110+
lastOrderByValue = currentOrderByValue
111+
hasLast = true
112+
}
113+
}
114+
115+
return !isEmpty(lastUrl) ? lastUrl : undefined
86116
}
87117

88118
const VIDEO_FILTERS = ({ isStream }) =>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict'
2+
3+
const test = require('ava')
4+
5+
const { getFormatUrls } = require('../src')
6+
7+
const getFormatUrl = getFormatUrls(() => [() => true], { orderBy: 'tbr' })
8+
9+
test('keep last format when orderBy values tie', t => {
10+
const input = {
11+
formats: [
12+
{ tbr: 128, url: 'https://example.com/first.mp4' },
13+
{ tbr: 128, url: 'https://example.com/second.mp4' }
14+
]
15+
}
16+
17+
const value = getFormatUrl(input, [], { isStream: false })
18+
t.is(value, 'https://example.com/second.mp4')
19+
})
20+
21+
test('keep undefined orderBy values at the end of ascending selection', t => {
22+
const input = {
23+
formats: [
24+
{ tbr: 128, url: 'https://example.com/with-tbr.mp4' },
25+
{ tbr: undefined, url: 'https://example.com/without-tbr.mp4' }
26+
]
27+
}
28+
29+
const value = getFormatUrl(input, [], { isStream: false })
30+
t.is(value, 'https://example.com/without-tbr.mp4')
31+
})

0 commit comments

Comments
 (0)