我目前有这个功能,通过 ffmpeg 管道传输多个 youtubedl 命令,然后将 ffmpeg 的输出管道传输到 HTTP 客户端。
func pipeThruFfmpegToMp4(vi *VideoInfo, rw web.ResponseWriter) error {
var ffmpeg *exec.Cmd
ffmpeg = exec.Command(
"ffmpeg",
"-i", "-",
"-i", "pipe:3",
"-c:v", "copy", "-c:a", "copy",
"-preset", "veryfast",
"-metadata", fmt.Sprintf(`title=%s`, vi.GetTitle()),
"-movflags", "frag_keyframe+empty_moov",
"-f", "mp4",
"-")
youtubevideo := exec.Command(YoutubeDLPath, "-c", "-f", fmt.Sprintf("%s/bestvideo[ext=mp4]/bestvideo/best", vi.GetFormat()), "--no-cache-dir", "--restrict-filenames", "--hls-prefer-native", "-o", "-", fmt.Sprintf("%s", vi.GetVideoUrl()))
fmt.Println(youtubevideo)
youtube := exec.Command(YoutubeDLPath, "-c", "-f", "bestaudio[ext=m4a]/bestaudio/best", "--no-cache-dir", "--restrict-filenames", "--hls-prefer-native", "-o", "-", fmt.Sprintf("%s", vi.GetVideoUrl()))
fmt.Println(youtube)
var ytvbuf, ytbuf, ffbuf bytes.Buffer
youtubevideo.Stderr = &ytvbuf
youtube.Stderr = &ytbuf
ffmpeg.Stderr = &ffbuf
video, err := youtubevideo.StdoutPipe()
if err != nil {
log.Printf("pipeThruFfmpegToMp4: %v\n", err)
return err
}
pipe3, err := youtube.StdoutPipe()
if err != nil {
log.Printf("pipeThruFfmpegToMp4: %v\n", err)
return err
}
ffmpeg.Stdin = video
ffmpeg.ExtraFiles = []*os.File{pipe3.(*os.File)}
ffmpeg.Stdout = rw
// Headers sent, no turning back now
rw.Header().Set("Content-Type", "video/mp4")
rw.Header().Set("Content-Disposition", fmt.Sprintf("attachment;filename=\"%s.mp4\"", vi.GetSlug()))
rw.Flush()
ffmpeg.Start()
youtubevideo.Start()
youtube.Start()
ffmpeg.Wait()
youtubevideo.Wait()
youtube.Wait()
问题是一切运行正常,但过了一会儿,内存开始填满服务器,直到它出现错误runtime/cgo: pthread_create failed: Resource temporarily unavailable
我不确定这是否是内存泄漏,或者 youtube-dl 的任一实例是否未正确关闭,或者 ffmpeg 是否未正确关闭并且随着程序运行更多而消耗越来越多的内存,直到程序因此错误而崩溃
慕标琳琳
富国沪深
相关分类