Mute the 'stream ended' clip's audio (#3630)

* Mute the 'stream ended' clip's audio

The 'stream ended' clip plays at the at the end of every stream broadcast using owncast.
It currently contains audio that peaks at -7.1db. (according to ffmpeg's volumedetect audio filter)
This can result in a bad experience for viewers if the stream that they were just watching had a much lower average volume, and they had turned up their speakers or headphones to compensate. In extreme cases this could theoretically cause harm to viewers and/or their equipment.
As an admin running owncast, there is no way to remove this audio *except* for patching the file. Even if you do patch the file, you need to notify your viewers to clear their browser caches if they have ever seen the clip, because offline.ts has a cache-control max-age header specifying 365 days. The caching of the previous version of this clip is out of scope of this PR.

This issue is discussed in more detail in #1965.

Unlike my previous attempt in #3332, which removed the audio track, this PR *mutes* the audio.

Specifically, I used this ffmpeg command:
```
ffmpeg -i offline.ts -filter:a "volume=0.0" output.ts
```

There are no other modifications to the clip.

* Commit updated API documentation

* feat(video): make compatible muted offline clip. Rename clip as a v2 so it is not cached

* Fix conflict

* force add new offline file

---------

Co-authored-by: vivlim <vivlim@vivl.im>
Co-authored-by: Owncast <owncast@owncast.online>
Co-authored-by: Gabe Kangas <gabek@real-ity.com>
This commit is contained in:
Vivian Lim ⭐ 2024-04-17 11:44:19 -07:00 committed by GitHub
parent d3b0cb261a
commit f81e8dcda7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 5 additions and 5 deletions

View file

@ -104,7 +104,7 @@ func transitionToOfflineVideoStreamContent() {
_transcoder.SetLatencyLevel(models.GetLatencyLevel(4))
_transcoder.SetIsEvent(true)
offlineFilePath, err := saveOfflineClipToDisk("offline.ts")
offlineFilePath, err := saveOfflineClipToDisk("offline-v2.ts")
if err != nil {
log.Fatalln("unable to save offline clip:", err)
}

View file

@ -36,7 +36,7 @@ func appendOfflineToVariantPlaylist(index int, playlistFilePath string) {
_, _ = atomicWriteTmpPlaylistFile.WriteString("#EXT-X-DISCONTINUITY\n")
// If "offline" content gets changed then change the duration below
_, _ = atomicWriteTmpPlaylistFile.WriteString("#EXTINF:8.000000,\n")
_, _ = atomicWriteTmpPlaylistFile.WriteString("offline.ts\n")
_, _ = atomicWriteTmpPlaylistFile.WriteString("offline-v2.ts\n")
_, _ = atomicWriteTmpPlaylistFile.WriteString("#EXT-X-ENDLIST\n")
if err := atomicWriteTmpPlaylistFile.Close(); err != nil {

View file

@ -93,7 +93,7 @@ func SetStreamAsDisconnected() {
_stats.LastConnectTime = nil
_broadcaster = nil
offlineFilename := "offline.ts"
offlineFilename := "offline-v2.ts"
offlineFilePath, err := saveOfflineClipToDisk(offlineFilename)
if err != nil {

BIN
static/offline-v2.ts vendored Normal file

Binary file not shown.

BIN
static/offline.tsclip vendored

Binary file not shown.

4
static/static.go vendored
View file

@ -51,12 +51,12 @@ func GetWebIndexTemplate() (*template.Template, error) {
return tmpl, err
}
//go:embed offline.tsclip
//go:embed offline-v2.ts
var offlineVideoSegment []byte
// GetOfflineSegment will return the offline video segment data.
func GetOfflineSegment() []byte {
return getFileSystemStaticFileOrDefault("offline.tsclip", offlineVideoSegment)
return getFileSystemStaticFileOrDefault("offline-v2.ts", offlineVideoSegment)
}
//go:embed img/logo.png