Skip to content

Commit bfc9f83

Browse files
committed
feat: set video location and format, download using bestvideo and --merge-output-format webm/mp4
1 parent 265e47a commit bfc9f83

File tree

4 files changed

+29
-13
lines changed

4 files changed

+29
-13
lines changed

client/components/video-element.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class VideoElement extends HTMLElement {
9191
watchVideoHandler (event) {
9292
event.preventDefault()
9393
this.querySelector('.play.video-placeholder').outerHTML = /*html*/`<video controls width="400">
94-
<source src="/videos/${this.video.id}" type="video/mp4" />
94+
<source src="/videos/${this.video.id}" type="video/${this.video.format}" />
9595
<track
9696
default
9797
kind="captions"

lib/repository.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,13 @@ export default class Repository {
3030
}
3131

3232
fs.readdirSync(`${this.basePath}/videos`).forEach(file => {
33-
if (!file.endsWith('.mp4') || file.endsWith('.uncut.mp4')) return
34-
const videoId = file.replace('.mp4', '')
35-
this.setVideoDownloaded(videoId)
33+
const format = file.substring(file.lastIndexOf('.') + 1)
34+
if (!['mp4', 'webm'].includes(format)) return
35+
if (file.includes('.uncut.')) return
36+
const videoId = file.replace('.mp4', '').replace('.webm', '')
37+
if (videoId.includes('.')) return // skip formats
38+
const location = `${this.basePath}/videos/${file}`
39+
this.updateVideo(videoId, {downloaded: true, location, format})
3640
})
3741
this.saveVideos()
3842
}

lib/server.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,11 @@ export function createServer ({repo, connections = []}) {
187187
}
188188

189189
function watchVideoHandler(req, res) {
190-
const videoPath = './data' + req.url + '.mp4'
191-
if (!fs.existsSync(videoPath)) {
190+
const id = req.url.replace('/videos/', '')
191+
const video = repo.getVideo(id)
192+
const location = video.location || `./data/videos/${id}.mp4`
193+
const contentType = video.format ? `video/${video.format}` : "video/mp4"
194+
if (!fs.existsSync(location)) {
192195
res.writeHead(404, { 'Content-Type': 'text/plain' })
193196
res.end('Video not found')
194197
return
@@ -218,8 +221,8 @@ export function createServer ({repo, connections = []}) {
218221
}
219222
}
220223
}
221-
res.setHeader("content-type", "video/mp4")
222-
const stat = fs.statSync(videoPath)
224+
res.setHeader("content-type", contentType)
225+
const stat = fs.statSync(location)
223226

224227
let contentLength = stat.size
225228

@@ -246,9 +249,9 @@ export function createServer ({repo, connections = []}) {
246249
res.setHeader("accept-ranges", "bytes")
247250
}
248251

249-
const fileStream = fs.createReadStream(videoPath, options)
252+
const fileStream = fs.createReadStream(location, options)
250253
fileStream.on("error", error => {
251-
console.log(`Error reading file ${videoPath}.`)
254+
console.log(`Error reading file ${location}.`)
252255
console.log(error)
253256
res.writeHead(500)
254257
res.end()

lib/youtube.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const fetchYoutubeHeaders = {
88
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
99
}
1010
const subtitlesYTDLPArgs = `--write-subs --write-auto-subs --sub-format vtt --convert-subs srt -k`
11-
const videoYTDLPArgs = `--concurrent-fragments 5 -f best[ext=mp4] --sponsorblock-remove sponsor`
11+
const videoYTDLPArgs = `--concurrent-fragments 5 --merge-output-format webm/mp4 -f bestvideo[height<=480]+bestaudio/best[height<=480] --sponsorblock-remove sponsor`
1212

1313
function getOptionalCookiesPath() {
1414
if (fs.existsSync('/app/cookies.txt')) return '/app/cookies.txt'
@@ -25,22 +25,31 @@ export async function downloadVideo(id, repo, callback = () => {}) {
2525
try {
2626
const cookiesPath = getOptionalCookiesPath()
2727
let cookiesOption = cookiesPath ? `--cookies ${cookiesPath}` : ''
28-
const commandArgs = `-o ./data/videos/${id}.mp4 ${cookiesOption} ${videoYTDLPArgs} ${subtitlesYTDLPArgs} -- ${id}`.split(/ +/)
28+
const commandArgs = `-o ./data/videos/${id}.%(ext)s ${cookiesOption} ${videoYTDLPArgs} ${subtitlesYTDLPArgs} -- ${id}`.split(/ +/)
2929
console.log('running yt-dlp', commandArgs.join(' '))
30+
let location, format
3031
for await (const line of spawn('yt-dlp', commandArgs)) {
3132
console.log(line)
3233
callback(line)
34+
if (line.startsWith('[Merger] Merging formats into')) {
35+
location = line.substring(line.lastIndexOf(' ') + 1).replace(/"/g,'')
36+
format = location.substring(location.lastIndexOf('.') + 1)
37+
}
3338
}
39+
console.log('downloaded file to', location)
3440

3541
if (!repo.getVideo(id)) {
3642
const video = await getVideo(id)
43+
video.location = location
44+
video.format = format
3745
repo.upsertVideos([video])
3846
callback(`downloaded external video ${id}`)
3947
}
48+
49+
repo.updateVideo(id, {downloaded: true, location, format})
4050

4151
normalizeSubtitleFiles(id)
4252

43-
repo.setVideoDownloaded(id)
4453
console.log('Download completed')
4554
resolve(id)
4655
} catch (error) {

0 commit comments

Comments
 (0)