* fix(s3): scope segment cleanup to path prefix, fix slice panic, batch deletes
When a path prefix is configured for S3 storage, uploads correctly
write to <prefix>/hls/... but cleanup lists objects from the bucket
root without the prefix. This causes a panic when the resulting
segment list is empty, due to unsafe slicing with a negative index.
- Centralize prefix construction in remoteHLSPrefix() so Save(),
retrieveAllVideoSegments(), and rewritePlaylistLocations() all
share the same logic. remoteHLSListingPrefix() adds a trailing
slash for directory-scoped S3 listing.
- Use strings.Trim to normalize both leading and trailing slashes
from the configured path prefix.
- Replace ListObjects with ListObjectsPages to handle buckets with
more than 1000 segments.
- Batch DeleteObjects calls in chunks of 1000 to respect the S3
API limit, and log per-object errors from the response.
- Guard getDeletableVideoSegmentsWithOffset against empty result
sets to prevent the slice bounds panic.
Fixes#4784
* fix(s3): handle empty hlsPrefix in rewritePlaylistLocations
LocalStorage calls rewritePlaylistLocations with an empty prefix.
The previous refactor removed the fallback to "/hls", causing
double slashes and missing path segments in playlist URLs.
Default hlsPrefix to "hls" when empty to preserve existing behavior
for local storage setups with a custom video serving endpoint.
* feat(ap): add validation+update+cleanup AP actor job
* fix(test): use time.Time instead of sql.NullTime
* feat(test): add integration test for AP follower cleanup/validation job
* feat(chat): require authentication to participate in chat
* fix: it's pretty much impossible to bypass the auth requirement, addressing review feedback anyway
* feat(chat): render chat text input as disabled if chat auth is required
* Commit updated API documentation
---------
Co-authored-by: Owncast <owncast@owncast.online>
* feat(ap): add support for shared inboxes to reduce outbound load
* feat(db): refactor ap followers db into followers repository
* fix(ap): use the updated activity library to pull out the shared inbox endpoint
* chore(deps): point at updated build of owncast/activity
* fix(ap): typeless endpoints
* feat(test): update ActivityPub test to support shared inboxes
* chore(test): remove unused variable
* fix: feedback from review. Guard against SSRF/non-HTTPS/local and handle transaction errors
* feat: Adds a webhook for when a user follow the stream
Frontend:
Adds a checkbox which renders only when social features are enabled.
Backend:
- Defines a new type for the event
- Implements the webhook including unit testing
- Fires the webhook inside the ApproveFollower handler
* Removes unnecessary Type fiels from Events struct
* refactor: renames SendUserFollowedEvent func to FediverseEngagementFollow and fixes linting errors
* fix: fixes unit test to reflect removed Type field from FediverseEngagementFollowEvent
* feat: fires webhook also when manual approvals are not required
* chore: slight cleanup
---------
Co-authored-by: Gabe Kangas <gabek@real-ity.com>
* Add support for Windows
* Fixes for Windows
* Update unit tests
* Fix ffreport setting
* Add test script equivalents
* Fix fontconfig error in test stream
* Fix thumbnail generator
* Fix lint warnings
* Fix warnings in test stream script
* Implement cross-platform ocTestStream
* Migrate to cross-platform script
* Revert ocTestStream.sh
* Add missing EOL
* Alternative test scripts for non-linux environments
---------
Co-authored-by: Gabe Kangas <gabek@real-ity.com>
* feat: enable Intel Quicksync with support for FFmpeg 4.x to 7.1
* fix(go): fix linter warning
---------
Co-authored-by: Gabe Kangas <gabek@real-ity.com>
* WIP
* fix(test): fix ap test failing
* fix: fix unkeyed fields being used
* chore(tests): clean up browser tests by splitting out federation UI tests
* It builds with the new user repository
* fix(test): fix broken test
* fix(api): fix registration endpoint that was broken after the change
* fix(test): update test to reflect new user repository
* fix: use interface type instead of concrete type
* fix: restore commented out code
* Add bcrypt hashing helpers
* SetAdminPassword now hashes the password before saving it
* BasicAuth now compares the bcrypt hash for the password
* Modify migration2 to avoid a double password hash when upgrading
* Add migration for bcrypt hashed password
* Do not show admin password hash as initial value
* Update api tests to compare the bcrypt hash of the admin password instead
* Remove old admin password api tests
---------
Co-authored-by: Gabe Kangas <gabek@real-ity.com>
* 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>
* feat(chat): basic profanity filter. For #3139
* feat(chat): add setting for disabling chat spam protection. Closes#3523
* feat(chat): wire up the new chat slur filter to admin and chat. Closes#3139