tgutils/audio.go (view raw)
1// Package tgutils provides extra functions to make certain tasks easier.
2package tgutils
3
4import (
5 "github.com/syfaro/telegram-bot-api"
6 "log"
7 "os"
8 "os/exec"
9 "path/filepath"
10 "strconv"
11 "sync"
12 "time"
13)
14
15var rand uint32
16var randmu sync.Mutex
17
18func reseed() uint32 {
19 return uint32(time.Now().UnixNano() + int64(os.Getpid()))
20}
21
22func nextSuffix() string {
23 randmu.Lock()
24 r := rand
25 if r == 0 {
26 r = reseed()
27 }
28 r = r*1664525 + 1013904223 // constants from Numerical Recipes
29 rand = r
30 randmu.Unlock()
31 return strconv.Itoa(int(1e9 + r%1e9))[1:]
32}
33
34// this function ripped from ioutils.TempFile, except with a suffix, instead of prefix.
35func tempFileWithSuffix(dir, suffix string) (f *os.File, err error) {
36 if dir == "" {
37 dir = os.TempDir()
38 }
39
40 nconflict := 0
41 for i := 0; i < 10000; i++ {
42 name := filepath.Join(dir, nextSuffix()+suffix)
43 f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
44 if os.IsExist(err) {
45 if nconflict++; nconflict > 10 {
46 randmu.Lock()
47 rand = reseed()
48 randmu.Unlock()
49 }
50 continue
51 }
52 break
53 }
54 return
55}
56
57// EncodeAudio takes a file and attempts to convert it to a .ogg for Telegram.
58// It then returns an AudioConfig.
59//
60// This function requires ffmpeg and opusenc to be installed on the system!
61func EncodeAudio(audio *tgbotapi.AudioConfig) error {
62 f, err := tempFileWithSuffix(os.TempDir(), "_tgutils.ogg")
63 if err != nil {
64 return err
65 }
66 defer f.Close()
67
68 log.Println(f.Name())
69
70 ffmpegArgs := []string{
71 "-i",
72 audio.FilePath,
73 "-f",
74 "wav",
75 "-",
76 }
77
78 opusArgs := []string{
79 "--bitrate",
80 "256",
81 "-",
82 f.Name(),
83 }
84
85 c1 := exec.Command("ffmpeg", ffmpegArgs...)
86 c2 := exec.Command("opusenc", opusArgs...)
87
88 c2.Stdin, _ = c1.StdoutPipe()
89 c2.Stdout = os.Stdout
90 c2.Start()
91 c1.Run()
92 c2.Wait()
93
94 return nil
95}