diff options
| author | Nathan Perry <avaglir@gmail.com> | 2017-07-28 00:51:34 -0400 |
|---|---|---|
| committer | Nathan Perry <avaglir@gmail.com> | 2017-07-28 00:51:34 -0400 |
| commit | 47877a3045c745e70b2e77a91e1f59e6f432c5df (patch) | |
| tree | dfcb8b1ea145c33c04aee45dd0c46824bf5fec36 | |
| parent | 54359c61daadf1d61730d224675c3b4595a5b83a (diff) | |
try own wav impl
| -rw-r--r-- | downloader/downloader.go | 80 | ||||
| -rw-r--r-- | downloader/downloader_test.go | 22 | ||||
| -rw-r--r-- | extramemes.go | 14 | ||||
| -rw-r--r-- | wav/wav.go | 177 | ||||
| -rw-r--r-- | wav/wav_test.go | 15 |
5 files changed, 308 insertions, 0 deletions
diff --git a/downloader/downloader.go b/downloader/downloader.go new file mode 100644 index 0000000..1ebaa1d --- /dev/null +++ b/downloader/downloader.go @@ -0,0 +1,80 @@ +package downloader + +import ( + "net/url" + "os/exec" + "strconv" + "time" + + "io/ioutil" + "os" + + "github.com/cryptix/wav" + "github.com/op/go-logging" +) + +var log = logging.MustGetLogger("downloader") + +func getUrl(inUrl string) (string, error) { + dl := exec.Command("youtube-dl", "-f", "bestaudio", "-x", "--get-url", inUrl) + + b, err := dl.CombinedOutput() + if err != nil { + log.Errorf("youtube-dl failed: %v", string(b)) + return "", err + } + + tgt, err := url.Parse(string(b)) + out := tgt.Scheme + "://" + tgt.Host + tgt.Path + "?" + tgt.Query().Encode() + + return out, nil +} + +func Download(inUrl string, startTime time.Duration, duration time.Duration) error { + targetUrl, err := getUrl(inUrl) + if err != nil { + return err + } + + startSecond := int(startTime.Seconds()) + dur := int(duration.Seconds()) + + args := []string{ + "-ss", strconv.Itoa(startSecond), + "-i", targetUrl, + "-c:a", "pcm_s16le", + "-f", "wav", + "-ar", "44100", + "-ac", "2", + "-vn", "-y", + } + + if dur > 0 { + args = append(args, "-t", strconv.Itoa(dur)) + } + + file, err := ioutil.TempFile("", "dl") + if err != nil { + return err + } + defer func() { + if err := os.Remove(file.Name()); err != nil { + log.Errorf("unable to remove temp file: %q", err) + } + }() + + args = append(args, file.Name()) + + dl := exec.Command(`ffmpeg`, args...) + b, err := dl.CombinedOutput() + if err != nil { + log.Errorf("ffmpeg failed: \n%v", string(b)) + return err + } + + wav.NewReader(file, ) + + + + return nil +} diff --git a/downloader/downloader_test.go b/downloader/downloader_test.go new file mode 100644 index 0000000..37a23d4 --- /dev/null +++ b/downloader/downloader_test.go @@ -0,0 +1,22 @@ +package downloader + +import ( + "fmt" + "testing" + "time" +) + +func TestGetUrl(t *testing.T) { + u, err := getUrl("https://www.youtube.com/watch?v=_K13GJkGvDw") + if err != nil { + t.Fatal(err) + } + + fmt.Println(u) +} + +func TestDownload(t *testing.T) { + if err := Download("https://www.youtube.com/watch?v=_K13GJkGvDw", 10*time.Second, 10*time.Second); err != nil { + t.Fatal(err) + } +} diff --git a/extramemes.go b/extramemes.go index 4bac256..fb2f8f6 100644 --- a/extramemes.go +++ b/extramemes.go @@ -2,6 +2,7 @@ package thulani import ( "math/rand" + "regexp" "strings" "time" ) @@ -13,6 +14,7 @@ func init() { var extraMemes = []func(*messageCtx) MemeStatus{ respondToFuckYou, respondToMeme, + respondToRaaaaaaaaaaaay, } var hateMatch = []string{ @@ -70,3 +72,15 @@ func respondToMeme(ctx *messageCtx) MemeStatus { ctx.sendMessage("i am not yet capable of memeing.", false) return Interrupt } + +var ray = regexp.MustCompile("ra+y") + +// TODO: play the sound clip +func respondToRaaaaaaaaaaaay(ctx *messageCtx) MemeStatus { + if ctx.Matched && ray.MatchString(ctx.Command) { + ctx.sendMessage(ctx.Command, true) + return Interrupt + } + + return Continue +} diff --git a/wav/wav.go b/wav/wav.go new file mode 100644 index 0000000..b82ec16 --- /dev/null +++ b/wav/wav.go @@ -0,0 +1,177 @@ +package wav + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "io/ioutil" + "os" +) + +type WavFile struct { + Header Header + Format FormatChunk + Data DataChunk +} + +type Header struct { + GroupID [4]uint8 + FileLength uint32 + RiffType [4]uint8 +} + +type FormatChunk struct { + GroupID [4]uint8 + ChunkSize uint32 + FormatTag uint16 + Channels uint16 + SampleRate uint32 + ByteRate uint32 + Alignment uint16 + BitDensity uint32 +} + +type DataChunk struct { + GroupID [4]uint8 + ChunkSize uint32 + Samples io.Reader +} + +func Load(filename string) (*WavFile, error) { + file, err := os.Open(filename) + + if err != nil { + return nil, err + } + + load16 := func(b []byte) (uint16, error) { + var out uint16 + err := binary.Read(bytes.NewBuffer(b), binary.LittleEndian, &out) + return out, err + } + + load32 := func(b []byte) (uint32, error) { + var out uint32 + err := binary.Read(bytes.NewBuffer(b), binary.LittleEndian, &out) + return out, err + + } + + b, err := ioutil.ReadAll(io.LimitReader(file, 40)) + if err != nil { + return nil, err + } + + h := Header{} + h.FileLength, err = load32(b[4:36]) + if err != nil { + return nil, err + } + h.FileLength -= 8 // subtract RIFF/WAVE markers + + for i := 0; i < 4; i++ { + h.GroupID[i] = b[i] + h.RiffType[i] = b[i+36] + } + + fmt.Println(h) + fmt.Println(string(h.RiffType[:])) + + if string(h.GroupID[:]) != "RIFF" { // || string(h.RiffType[:]) != "WAVE" { + return nil, fmt.Errorf("invalid header!") + } + + f := FormatChunk{} + + file.Seek(40, io.SeekStart) + b, err = ioutil.ReadAll(io.LimitReader(file, 36)) + if err != nil { + return nil, err + } + + for i := 0; i < 4; i++ { + f.GroupID[i] = b[i] + } + + f.ChunkSize, err = load32(b[4:36]) + if err != nil { + return nil, err + } + + file.Seek(76, io.SeekStart) + b, err = ioutil.ReadAll(io.LimitReader(file, int64(f.ChunkSize))) + if err != nil { + return nil, err + } + + f.FormatTag, err = load16(b[36:52]) + if err != nil { + return nil, err + } + + f.Channels, err = load16(b[52:68]) + if err != nil { + return nil, err + } + + f.SampleRate, err = load32(b[68:100]) + if err != nil { + return nil, err + } + + f.ByteRate, err = load32(b[100:132]) + if err != nil { + return nil, err + } + + f.Alignment, err = load16(b[132:148]) + if err != nil { + return nil, err + } + + f.BitDensity, err = load32(b[138:180]) + if err != nil { + return nil, err + } + + if string(f.GroupID[:]) != "fmt " || + f.FormatTag != 1 || + f.Alignment != uint16((uint32(f.Channels)*f.BitDensity/8)&0xff) { + return nil, fmt.Errorf("invalid format block!") + } + + if f.BitDensity != 16 || f.Channels != 2 || f.SampleRate != 44100 { + return nil, fmt.Errorf("wrong pcm format!") + } + + d := DataChunk{} + + file.Seek(220, io.SeekStart) + b, err = ioutil.ReadAll(io.LimitReader(file, 36)) + if err != nil { + return nil, err + } + + for i := 0; i < 4; i++ { + d.GroupID[i] = b[i] + } + + d.ChunkSize, err = load32(b[4:]) + if err != nil { + return nil, err + } + + if string(f.GroupID[:]) != "fmt " { + return nil, fmt.Errorf("invalid data block!") + } + + file.Seek(256, io.SeekStart) + d.Samples = io.LimitReader(file, int64(d.ChunkSize)) + + return &WavFile{ + Header: h, + Format: f, + Data: d, + }, nil +} diff --git a/wav/wav_test.go b/wav/wav_test.go new file mode 100644 index 0000000..4fa64db --- /dev/null +++ b/wav/wav_test.go @@ -0,0 +1,15 @@ +package wav + +import ( + "fmt" + "testing" +) + +func TestLoad(t *testing.T) { + wf, err := Load("../downloader/out.wav") + if err != nil { + t.Error(err) + } + + fmt.Println(wf) +} |
