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)
|
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)
|
||||||
─────────────────────────────── */
|
─────────────────────────────── */
|
||||||
|
|||||||
BIN
recorder.exe
BIN
recorder.exe
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user