commit 79d02d2c714ae396aa780551bb8c50d9931ae0e9
parent 203c498531d7359475fca41271345978300cfada
Author: breadcat <breadcat@users.noreply.github.com>
Date: Wed, 24 Sep 2025 14:50:47 +0100
Add videos using yt-dlp
Diffstat:
2 files changed, 75 insertions(+), 0 deletions(-)
diff --git a/main.go b/main.go
@@ -230,6 +230,7 @@ func main() {
http.HandleFunc("/", listFilesHandler)
http.HandleFunc("/add", uploadHandler)
+ http.HandleFunc("/add-yt", ytdlpHandler)
http.HandleFunc("/upload-url", uploadFromURLHandler)
http.HandleFunc("/file/", fileRouter)
http.HandleFunc("/tags", tagsHandler)
@@ -955,6 +956,74 @@ func settingsHandler(w http.ResponseWriter, r *http.Request) {
tmpl.ExecuteTemplate(w, "settings.html", pageData)
}
+// yt-dlp Handler
+func ytdlpHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ http.Redirect(w, r, "/upload", http.StatusSeeOther)
+ return
+ }
+
+ videoURL := r.FormValue("url")
+ if videoURL == "" {
+ http.Error(w, "No URL provided", http.StatusBadRequest)
+ return
+ }
+
+ // Step 1: Get the expected filename first
+ outTemplate := filepath.Join(config.UploadDir, "%(title)s.%(ext)s")
+ filenameCmd := exec.Command("yt-dlp", "-f", "mp4", "-o", outTemplate, "--get-filename", videoURL)
+ filenameBytes, err := filenameCmd.Output()
+ if err != nil {
+ http.Error(w, fmt.Sprintf("Failed to get filename: %v", err), http.StatusInternalServerError)
+ return
+ }
+ expectedFilename := strings.TrimSpace(string(filenameBytes))
+
+ // Enforce strict duplicate check
+ finalFilename, finalPath, err := checkFileConflictStrict(expectedFilename)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusConflict)
+ return
+ }
+ finalTemplate := filepath.Join(config.UploadDir, finalFilename)
+
+ // Step 2: Download with yt-dlp to the final path
+ downloadCmd := exec.Command("yt-dlp", "-f", "mp4", "-o", finalTemplate, videoURL)
+ downloadCmd.Stdout = os.Stdout
+ downloadCmd.Stderr = os.Stderr
+ if err := downloadCmd.Run(); err != nil {
+ http.Error(w, fmt.Sprintf("Failed to download video: %v", err), http.StatusInternalServerError)
+ return
+ }
+
+ // Step 3: Process video (codec detection and potential re-encoding)
+ // Create a temporary path for processing
+ tempPath := finalPath + ".tmp"
+ os.Rename(finalPath, tempPath) // Move downloaded file to temp location
+
+ processedPath, warningMsg, err := processVideoFile(tempPath, finalPath)
+ if err != nil {
+ os.Remove(tempPath) // Clean up
+ http.Error(w, fmt.Sprintf("Failed to process video: %v", err), http.StatusInternalServerError)
+ return
+ }
+
+ // Step 4: Save to database
+ id, err := saveFileToDatabase(finalFilename, processedPath)
+ if err != nil {
+ os.Remove(processedPath)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // Step 5: Redirect with optional warning
+ redirectURL := fmt.Sprintf("/file/%d", id)
+ if warningMsg != "" {
+ redirectURL += "?warning=" + url.QueryEscape(warningMsg)
+ }
+ http.Redirect(w, r, redirectURL, http.StatusSeeOther)
+}
+
// Parse file ID ranges like "1-3,6,9" into a slice of integers
func parseFileIDRange(rangeStr string) ([]int, error) {
var fileIDs []int
diff --git a/templates/add.html b/templates/add.html
@@ -12,4 +12,10 @@
<button type="submit">Add File</button>
</form>
+<h2>Upload from yt-dlp</h2>
+<form action="/add-yt" method="POST">
+ <label for="url">Video URL:</label>
+ <input type="text" name="url" id="url" required>
+ <button type="submit">Add Video</button>
+</form>
{{template "_footer"}}
\ No newline at end of file