Skip to content

Commit

Permalink
Add /api/ffmpeg for playing files and tts on cameras with two-way audio
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexxIT committed May 24, 2024
1 parent bf3f81c commit b3e9ed2
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 4 deletions.
51 changes: 51 additions & 0 deletions internal/ffmpeg/api.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
3 changes: 3 additions & 0 deletions internal/ffmpeg/ffmpeg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -40,6 +41,8 @@ func Init() {

streams.HandleFunc("ffmpeg", NewProducer)

api.HandleFunc("api/ffmpeg", apiFFmpeg)

device.Init(defaults["bin"])
hardware.Init(defaults["bin"])
}
Expand Down
13 changes: 9 additions & 4 deletions www/links.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,21 @@ <h2>MJPEG source</h2>

<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>
Expand Down

0 comments on commit b3e9ed2

Please sign in to comment.