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