github.com/0chain/gosdk@v1.17.11/zboxcore/sdk/live_upload_reader_youtubedl.go (about) 1 package sdk 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "os" 8 "os/exec" 9 "strconv" 10 "strings" 11 ) 12 13 // YoutubeDL wrap youtube-dl to download video from youtube 14 type YoutubeDL struct { 15 ctx context.Context 16 17 liveUploadReaderBase 18 19 // cmdYoutubeDL youtube-dl command 20 cmdYoutubeDL *exec.Cmd 21 22 // cmdFfmpeg ffmpeg command 23 cmdFfmpeg *exec.Cmd 24 } 25 26 // CreateYoutubeDL create a youtube-dl instance to download video file from youtube 27 // - localPath: output file path 28 // - feedURL: youtube video url 29 // - downloadArgs: youtube-dl download arguments 30 // - ffmpegArgs: ffmpeg arguments 31 // - delay: delay in seconds 32 func CreateYoutubeDL(ctx context.Context, localPath string, feedURL string, downloadArgs []string, ffmpegArgs []string, delay int) (*YoutubeDL, error) { 33 34 //youtube-dl -f best https://www.youtube.com/watch?v=RfUVIwnsvS8 --proxy http://127.0.0.1:8000 -o - | ffmpeg -i - -flags +cgop -g 30 -hls_time 5 youtube.m3u8 35 36 builder := createFileNameBuilder(localPath) 37 38 argsYoutubeDL := append(downloadArgs, 39 "-o", "-", 40 feedURL) //output to stdout 41 42 //argsYoutubeDL = append(argsYoutubeDL) 43 44 fmt.Println("[cmd]", "youtube-dl", strings.Join(argsYoutubeDL, " ")) 45 46 r, w := io.Pipe() 47 48 cmdYoutubeDL := exec.Command("youtube-dl", argsYoutubeDL...) 49 cmdYoutubeDL.Stderr = os.Stderr 50 cmdYoutubeDL.Stdout = w 51 52 argsFfmpeg := []string{"-i", "-"} 53 54 argsFfmpeg = append(argsFfmpeg, ffmpegArgs...) 55 argsFfmpeg = append(argsFfmpeg, 56 "-flags", "+cgop", 57 "-g", "30", 58 "-hls_time", strconv.Itoa(delay), 59 builder.OutFile()) 60 61 fmt.Println("[cmd]ffmpeg", strings.Join(argsFfmpeg, " ")) 62 cmdFfmpeg := exec.Command("ffmpeg", argsFfmpeg...) 63 cmdFfmpeg.Stderr = os.Stderr 64 cmdFfmpeg.Stdin = r 65 cmdFfmpeg.Stdout = os.Stdout 66 67 err := cmdYoutubeDL.Start() 68 if err != nil { 69 return nil, err 70 } 71 72 err = cmdFfmpeg.Start() 73 if err != nil { 74 return nil, err 75 } 76 77 dl := &YoutubeDL{ 78 ctx: ctx, 79 liveUploadReaderBase: liveUploadReaderBase{ 80 builder: builder, 81 delay: delay, 82 clipsIndex: 0, 83 }, 84 cmdYoutubeDL: cmdYoutubeDL, 85 cmdFfmpeg: cmdFfmpeg, 86 } 87 88 go dl.wait() 89 90 return dl, nil 91 } 92 93 func (r *YoutubeDL) wait() { 94 95 go func() { 96 <-r.ctx.Done() 97 r.Close() 98 }() 99 100 go func() { 101 r.err = r.cmdFfmpeg.Wait() 102 }() 103 104 r.err = r.cmdYoutubeDL.Wait() 105 } 106 107 // Close implements io.Closer 108 func (r *YoutubeDL) Close() error { 109 if r != nil { 110 if r.cmd != nil { 111 r.cmd.Process.Kill() //nolint 112 } 113 114 if r.cmdYoutubeDL != nil { 115 r.cmdYoutubeDL.Process.Kill() //nolint 116 } 117 118 if r.cmdFfmpeg != nil { 119 r.cmdFfmpeg.Process.Kill() //nolint 120 } 121 122 if r.clipsReader != nil { 123 r.clipsReader.Close() 124 } 125 } 126 127 return nil 128 }