Add /api/ffmpeg for playing files and tts on cameras with two-way audio

This commit is contained in:
Alex X
2024-05-24 12:49:37 +03:00
parent bf3f81ccac
commit b3e9ed23ac
3 changed files with 63 additions and 4 deletions

51
internal/ffmpeg/api.go Normal file
View File

@@ -0,0 +1,51 @@
package ffmpeg
import (
"net/http"
"strings"
"github.com/AlexxIT/go2rtc/internal/streams"
)
func apiFFmpeg(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "", http.StatusMethodNotAllowed)
return
}
query := r.URL.Query()
dst := query.Get("dst")
stream := streams.Get(dst)
if stream == nil {
http.Error(w, "", http.StatusNotFound)
return
}
var src string
if s := query.Get("file"); s != "" {
if streams.Validate(s) == nil {
src = "ffmpeg:" + s + "#audio=auto#input=file"
}
} else if s = query.Get("live"); s != "" {
if streams.Validate(s) == nil {
src = "ffmpeg:" + s + "#audio=auto"
}
} else if s = query.Get("text"); s != "" {
if strings.IndexAny(s, `'"&%$`) < 0 {
src = "ffmpeg:tts?text=" + s
if s = query.Get("voice"); s != "" {
src += "&voice=" + s
}
src += "#audio=auto"
}
}
if src == "" {
http.Error(w, "", http.StatusBadRequest)
return
}
if err := stream.Play(src); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}

View File

@@ -5,6 +5,7 @@ import (
"slices"
"strings"
"github.com/AlexxIT/go2rtc/internal/api"
"github.com/AlexxIT/go2rtc/internal/app"
"github.com/AlexxIT/go2rtc/internal/ffmpeg/device"
"github.com/AlexxIT/go2rtc/internal/ffmpeg/hardware"
@@ -40,6 +41,8 @@ func Init() {
streams.HandleFunc("ffmpeg", NewProducer)
api.HandleFunc("api/ffmpeg", apiFFmpeg)
device.Init(defaults["bin"])
hardware.Init(defaults["bin"])
}

View File

@@ -85,16 +85,21 @@
<div>
<h2>Play audio</h2>
<pre>example: ffmpeg:https://example.com/song.mp3#audio=pcma#input=file</pre>
<input id="play-url" type="text" placeholder="url">
<label><input type="radio" name="play" value="file" checked>file - play remote (https://example.com/song.mp3) or local (/media/song.mp3) file</label><br>
<label><input type="radio" name="play" value="live">live - play remote live stream (radio, etc.)</label><br>
<label><input type="radio" name="play" value="text">text - play Text To Speech (if your FFmpeg support this)</label><br>
<br>
<input id="play-url" type="text" placeholder="path / url / text">
<a id="play-send" href="#">send</a> / cameras with two way audio support
</div>
<script>
document.getElementById('play-send').addEventListener('click', ev => {
ev.preventDefault();
const url = new URL('api/streams', location.href);
// action - file / live / text
const action = document.querySelector('input[name="play"]:checked').value;
const url = new URL('api/ffmpeg', location.href);
url.searchParams.set('dst', src);
url.searchParams.set('src', document.getElementById('play-url').value);
url.searchParams.set(action, document.getElementById('play-url').value);
fetch(url, {method: 'POST'});
});
</script>