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}) => {
|
route: "/watch", methods: ["GET", "POST"], upload: true, code: async ({req, url, body}) => {
|
||||||
const user = getUser(req)
|
const user = getUser(req)
|
||||||
const settings = user.getSettingsOrDefaults()
|
const settings = user.getSettingsOrDefaults()
|
||||||
if (req.method === "GET") {
|
|
||||||
const id = url.searchParams.get("v")
|
const id = url.searchParams.get("v")
|
||||||
|
if (req.method === "GET") {
|
||||||
|
const t = url.searchParams.get("t")
|
||||||
|
let mediaFragment = converters.tToMediaFragment(t)
|
||||||
if (!settings.local) {
|
if (!settings.local) {
|
||||||
const instanceOrigin = settings.instance
|
const instanceOrigin = settings.instance
|
||||||
const outURL = `${instanceOrigin}/api/v1/videos/${id}`
|
const outURL = `${instanceOrigin}/api/v1/videos/${id}`
|
||||||
const videoPromise = request(outURL).then(res => res.json())
|
const videoPromise = request(outURL).then(res => res.json())
|
||||||
return renderVideo(videoPromise, {user, id, instanceOrigin})
|
return renderVideo(videoPromise, {user, id, instanceOrigin}, {mediaFragment})
|
||||||
} else {
|
} else {
|
||||||
return render(200, "pug/local-video.pug", {id})
|
return render(200, "pug/local-video.pug", {id})
|
||||||
}
|
}
|
||||||
} else { // req.method === "POST"
|
} else { // req.method === "POST"
|
||||||
const video = JSON.parse(new URLSearchParams(body.toString()).get("video"))
|
const video = JSON.parse(new URLSearchParams(body.toString()).get("video"))
|
||||||
const videoPromise = Promise.resolve(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]
|
- const format = sortedFormatStreams[0]
|
||||||
if format
|
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
|
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
|
else
|
||||||
video(src="")#video.video
|
video(src="")#video.video
|
||||||
.stream-notice The server provided no playback streams.
|
.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.timeToPastText = timeToPastText
|
||||||
module.exports.lengthSecondsToLengthText = lengthSecondsToLengthText
|
module.exports.lengthSecondsToLengthText = lengthSecondsToLengthText
|
||||||
module.exports.normaliseVideoInfo = normaliseVideoInfo
|
module.exports.normaliseVideoInfo = normaliseVideoInfo
|
||||||
|
module.exports.tToMediaFragment = tToMediaFragment
|
||||||
|
|
Loading…
Reference in New Issue