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
|
package downloader
import (
"time"
)
// DownloadManager handles a download for a particular song.
type DownloadManager struct {
Url string
Start time.Duration
Duration time.Duration
End time.Duration
pb chan (<-chan []byte)
info videoInfo
}
const clipTime = 10 * time.Second
const preloadCount = 5
func NewDownload(url string, startTime, dur time.Duration) (*DownloadManager, error) {
vInfo, err := info(url)
if err != nil {
return nil, err
}
if dur == 0 {
dur = vInfo.Duration - startTime
}
dl := &DownloadManager{
Url: url,
Start: startTime,
Duration: dur,
End: startTime + dur,
pb: make(chan (<-chan []byte), preloadCount),
info: *vInfo,
}
go dl.schedule()
return dl, nil
}
func (d *DownloadManager) SendOn(ch chan<- []byte) <-chan struct{} {
out := make(chan struct{}, 1)
go func() {
defer close(out)
for c := range d.pb {
for b := range c {
ch <- b
}
}
}()
return out
}
func (d *DownloadManager) schedule() {
go func() {
defer close(d.pb)
for i := 0; ; i++ {
clipStart := time.Duration(i)*clipTime + d.Start
clipEnd := time.Duration(i+1)*clipTime + d.Start
if clipStart >= d.End {
return
}
dur := clipTime
if clipEnd > d.End {
dur = d.End - clipStart
}
ch, err := d.download(clipStart, dur)
if err != nil {
log.Errorf("error setting up download: %q", err)
return
}
d.pb <- ch
}
}()
}
|