all repos — telegram-bot-api @ e1a0a819c0036d628c5ef449135c7963006f7cbc

Golang bindings for the Telegram Bot API

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