Support t parameter using media fragments
This commit is contained in:
parent
36f33b9f7e
commit
bb4816c4b3
|
@ -122,20 +122,23 @@ module.exports = [
|
|||
route: "/watch", methods: ["GET", "POST"], upload: true, code: async ({req, url, body}) => {
|
||||
const user = getUser(req)
|
||||
const settings = user.getSettingsOrDefaults()
|
||||
if (req.method === "GET") {
|
||||
const id = url.searchParams.get("v")
|
||||
if (req.method === "GET") {
|
||||
const t = url.searchParams.get("t")
|
||||
let mediaFragment = converters.tToMediaFragment(t)
|
||||
if (!settings.local) {
|
||||
const instanceOrigin = settings.instance
|
||||
const outURL = `${instanceOrigin}/api/v1/videos/${id}`
|
||||
const videoPromise = request(outURL).then(res => res.json())
|
||||
return renderVideo(videoPromise, {user, id, instanceOrigin})
|
||||
return renderVideo(videoPromise, {user, id, instanceOrigin}, {mediaFragment})
|
||||
} else {
|
||||
return render(200, "pug/local-video.pug", {id})
|
||||
}
|
||||
} else { // req.method === "POST"
|
||||
const video = JSON.parse(new URLSearchParams(body.toString()).get("video"))
|
||||
const videoPromise = Promise.resolve(video)
|
||||
return renderVideo(videoPromise, {user})
|
||||
const instanceOrigin = "http://localhost:3000"
|
||||
return renderVideo(videoPromise, {user, id, instanceOrigin})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ block content
|
|||
- const format = sortedFormatStreams[0]
|
||||
if format
|
||||
video(controls preload="auto" poster=`/vi/${video.videoId}/maxresdefault.jpg` width=format.second__width height=format.second__height data-itag=format.itag)#video.video
|
||||
source(src=format.url type=format.type)
|
||||
source(src=format.url+mediaFragment type=format.type)
|
||||
else
|
||||
video(src="")#video.video
|
||||
.stream-notice The server provided no playback streams.
|
||||
|
|
|
@ -47,6 +47,55 @@ function normaliseVideoInfo(video) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* YT supports a time parameter t in these possible formats:
|
||||
* - [digits] -> seconds
|
||||
* - ([digits]:)?[digits]:[digits] -> hours?, minutes, seconds
|
||||
* - ([digits]h)?([digits]m)?([digits]s)? -> hours?, minutes?, seconds
|
||||
*
|
||||
* Try our best to get something suitable out. Fail by returning empty
|
||||
* string, meaning nothing suitable was recognised.
|
||||
*/
|
||||
function tToMediaFragment(t) {
|
||||
let resolved = ""
|
||||
|
||||
console.log(t)
|
||||
if (!t || t.length > 10) { // don't parse missing values, don't pass too long strings
|
||||
// skip processing
|
||||
} else if (t.match(/^[0-9.,]+$/)) {
|
||||
resolved = t
|
||||
} else if (t.includes(":")) {
|
||||
resolved = t.split(":").map(s => s.padStart(2, "0")).join(":") // need to pad each to length 2 for npt
|
||||
} else if (t.match(/[hms]/)) {
|
||||
let buffer = ""
|
||||
let sum = 0
|
||||
const multipliers = new Map([
|
||||
["h", 60*60],
|
||||
["m", 60],
|
||||
["s", 1]
|
||||
])
|
||||
for (const char of t) {
|
||||
console.log(char)
|
||||
if (char.match(/[0-9]/)) {
|
||||
buffer += char
|
||||
} else if (char.match(/[hms]/)) {
|
||||
sum += +buffer * multipliers.get(char)
|
||||
buffer = ""
|
||||
} else {
|
||||
buffer = ""
|
||||
}
|
||||
}
|
||||
resolved = String(sum)
|
||||
}
|
||||
|
||||
if (resolved) {
|
||||
return "#t=npt:" + resolved
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.timeToPastText = timeToPastText
|
||||
module.exports.lengthSecondsToLengthText = lengthSecondsToLengthText
|
||||
module.exports.normaliseVideoInfo = normaliseVideoInfo
|
||||
module.exports.tToMediaFragment = tToMediaFragment
|
||||
|
|
Loading…
Reference in New Issue