This commit is contained in:
Linrador 2025-11-13 13:57:56 +01:00
parent c5993a05e0
commit 28023bfd3c
2 changed files with 97 additions and 9 deletions

106
main.go
View File

@ -403,7 +403,7 @@ func handleM3U8Mode(m3u8URL, outArg string) error {
return fmt.Errorf("ungültige URL: %q", m3u8URL) return fmt.Errorf("ungültige URL: %q", m3u8URL)
} }
// kleinen Check machen, ob abrufbar // Erreichbarkeit kurz prüfen
resp, err := http.Get(m3u8URL) resp, err := http.Get(m3u8URL)
if err != nil { if err != nil {
return fmt.Errorf("Abruf fehlgeschlagen: %w", err) return fmt.Errorf("Abruf fehlgeschlagen: %w", err)
@ -414,13 +414,14 @@ func handleM3U8Mode(m3u8URL, outArg string) error {
return fmt.Errorf("HTTP %d beim Abruf der m3u8", resp.StatusCode) return fmt.Errorf("HTTP %d beim Abruf der m3u8", resp.StatusCode)
} }
// Ausgabedatei // Ausgabedatei bestimmen
outFile := outArg outFile := strings.TrimSpace(outArg)
if strings.TrimSpace(outFile) == "" { if outFile == "" {
def := "mfc_" + time.Now().Format("20060102_150405") + ".mp4" def := "mfc_" + time.Now().Format("20060102_150405") + ".mp4"
fmt.Printf("Name der MP4-Datei (Enter für %s): ", def) fmt.Printf("Name der MP4-Datei (Enter für %s): ", def)
outFile = readLine() if s := readLine(); s != "" {
if strings.TrimSpace(outFile) == "" { outFile = s
} else {
outFile = def outFile = def
} }
} }
@ -434,14 +435,17 @@ func handleM3U8Mode(m3u8URL, outArg string) error {
} }
} }
// ffmpeg copy-download // ── 1) Live-fähiges, fragmentiertes MP4 schreiben (copy) ──────────
// WICHTIG: -bsf:a aac_adtstoasc setzen + explizit mappen
fmt.Println("📦 Starte Download mit ffmpeg:", outFile) fmt.Println("📦 Starte Download mit ffmpeg:", outFile)
cmd := exec.Command( cmd := exec.Command(
"ffmpeg", "ffmpeg",
"-nostdin", "-y", "-nostdin", "-y",
"-fflags", "+genpts", "-fflags", "+genpts",
"-i", m3u8URL, "-i", m3u8URL,
"-c", "copy", "-map", "0:v:0", "-map", "0:a:0?",
"-c:v", "copy",
"-c:a", "copy",
"-bsf:a", "aac_adtstoasc", "-bsf:a", "aac_adtstoasc",
"-movflags", "+frag_keyframe+empty_moov+default_base_moof", "-movflags", "+frag_keyframe+empty_moov+default_base_moof",
"-f", "mp4", "-f", "mp4",
@ -453,11 +457,95 @@ func handleM3U8Mode(m3u8URL, outArg string) error {
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
return fmt.Errorf("ffmpeg fehlgeschlagen: %w", err) return fmt.Errorf("ffmpeg fehlgeschlagen: %w", err)
} }
fmt.Println("✅ Download abgeschlossen:", outFile) fmt.Println("✅ Download abgeschlossen:", outFile)
// ── 2) Finales Remux in +faststart (für blitzschnelles Öffnen) ────
fmt.Println("🔁 Remux in finales MP4 (faststart)…")
if err := remuxMP4Faststart(outFile); err != nil {
fmt.Println("⚠️ Remux-Fehler:", err)
} else {
fmt.Println("✅ Remux abgeschlossen:", outFile)
}
return nil return nil
} }
// remuxMP4Faststart remuxt ein (ggf. fragmentiertes) MP4 in finales MP4 mit +faststart.
// 1. Versuch: copy/copy. Wenn danach kein Audio vorhanden ist, 2. Versuch mit AAC-Reencode.
func remuxMP4Faststart(inPath string) error {
base := strings.TrimSuffix(inPath, filepath.Ext(inPath))
tmp := base + ".remux.mp4"
hadAudioBefore, _ := hasAudioTrack(inPath) // nur zur Info/Fallback
// 1) Copy-Remux
if err := runCmd("ffmpeg",
"-y",
"-i", inPath,
"-map", "0:v:0", "-map", "0:a:0?",
"-c:v", "copy",
"-c:a", "copy",
"-movflags", "+faststart",
tmp,
); err != nil {
return fmt.Errorf("ffmpeg remux (copy) fehlgeschlagen: %w", err)
}
hasAudioAfter, _ := hasAudioTrack(tmp)
if !hasAudioAfter && hadAudioBefore {
// 2) Fallback: remux mit Audio-Reencode (wem auch immer copy schiefging)
_ = os.Remove(tmp)
if err := runCmd("ffmpeg",
"-y",
"-i", inPath,
"-map", "0:v:0", "-map", "0:a:0?",
"-c:v", "copy",
"-c:a", "aac", "-b:a", "192k",
"-movflags", "+faststart",
tmp,
); err != nil {
return fmt.Errorf("ffmpeg remux (aac-fallback) fehlgeschlagen: %w", err)
}
}
// Original durch remuxtes ersetzen
if err := os.Remove(inPath); err != nil {
return fmt.Errorf("remux ok, aber konnte Original nicht entfernen: %w", err)
}
if err := os.Rename(tmp, inPath); err != nil {
return fmt.Errorf("remux ok, aber konnte Zieldatei nicht umbenennen: %w", err)
}
return nil
}
func runCmd(name string, args ...string) error {
cmd := exec.Command(name, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
// hasAudioTrack prüft mit ffprobe, ob mind. ein Audiostream vorhanden ist.
func hasAudioTrack(path string) (bool, error) {
// ffprobe -v error -select_streams a -show_entries stream=index -of csv=p=0 <file>
out := &bytes.Buffer{}
cmd := exec.Command("ffprobe",
"-v", "error",
"-select_streams", "a",
"-show_entries", "stream=index",
"-of", "csv=p=0",
path,
)
cmd.Stdout = out
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return false, err
}
// Wenn irgendwas zurückkommt, gibt's Audio
return strings.TrimSpace(out.String()) != "", nil
}
/* /*
Chaturbate-Helpers (aus deiner Datei) Chaturbate-Helpers (aus deiner Datei)
*/ */

Binary file not shown.