updated
This commit is contained in:
parent
c5993a05e0
commit
28023bfd3c
106
main.go
106
main.go
@ -403,7 +403,7 @@ func handleM3U8Mode(m3u8URL, outArg string) error {
|
||||
return fmt.Errorf("ungültige URL: %q", m3u8URL)
|
||||
}
|
||||
|
||||
// kleinen Check machen, ob abrufbar
|
||||
// Erreichbarkeit kurz prüfen
|
||||
resp, err := http.Get(m3u8URL)
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
// Ausgabedatei
|
||||
outFile := outArg
|
||||
if strings.TrimSpace(outFile) == "" {
|
||||
// Ausgabedatei bestimmen
|
||||
outFile := strings.TrimSpace(outArg)
|
||||
if outFile == "" {
|
||||
def := "mfc_" + time.Now().Format("20060102_150405") + ".mp4"
|
||||
fmt.Printf("Name der MP4-Datei (Enter für %s): ", def)
|
||||
outFile = readLine()
|
||||
if strings.TrimSpace(outFile) == "" {
|
||||
if s := readLine(); s != "" {
|
||||
outFile = s
|
||||
} else {
|
||||
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)
|
||||
cmd := exec.Command(
|
||||
"ffmpeg",
|
||||
"-nostdin", "-y",
|
||||
"-fflags", "+genpts",
|
||||
"-i", m3u8URL,
|
||||
"-c", "copy",
|
||||
"-map", "0:v:0", "-map", "0:a:0?",
|
||||
"-c:v", "copy",
|
||||
"-c:a", "copy",
|
||||
"-bsf:a", "aac_adtstoasc",
|
||||
"-movflags", "+frag_keyframe+empty_moov+default_base_moof",
|
||||
"-f", "mp4",
|
||||
@ -453,11 +457,95 @@ func handleM3U8Mode(m3u8URL, outArg string) error {
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("ffmpeg fehlgeschlagen: %w", err)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
─────────────────────────────── */
|
||||
|
||||
BIN
recorder.exe
BIN
recorder.exe
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user