WatchTower - Video Sharing banner

WatchTower - Video Sharing

27 devlogs
64h 24m 15s

An open source video sharing app with recommendations, transcoding and more

Demo Repository

Loading README...

ultraviolet.asdf

Shipped this project!

I updated my video sharing app!

In this update I polished code, started work on an iOS app and added suggested videos in the view video page!

Please check my previous ship message and devlogs for more details :)

ultraviolet.asdf

Polishing

I refactored some ridiculous code that was inline, and made it a separate function.
This will reduce allot of bandwidth because now the JavaScript is in one place instead of in every single comment

View Commit

Attachment
0
ultraviolet.asdf

Polishing

Spent some time polishing things, and working on docker images, for a move to another server

  • 612a3cecad I removed the dependency on go-sqlite3 which was leftover from when I used sqlite as the database. The error messages for duplicate usernames are now prettier
  • fc2f524b21 I added docker images
  • e6394fea10 I gave the icons when changing/uploading thumbnails a background, so the contrast is still OK when the uploaded image is light or dark
  • 1427c28e33 I allowed the recommended videos to be clicked anywhere for better UX, and added a background on hover

If you spot anything that needs polishing - please let me know!

Attachment
Attachment
Attachment
0
ultraviolet.asdf

iOS App: Update

  1. I added sort options, you can now select between latest, popular, recommended and trending. This took a fair amount of work, I had to guess the type of the gRPC client so I could pass it between Views. This is really hard when you don’t have a functional LSP. I also had to rewrite the way the gRPC client was created so the connection doesn’t close.
  2. Moved thumbnails to a separate component for clarity
0
ultraviolet.asdf

Web Update

I added suggested videos right in the view video page.

I also simplified a lot of repeated code, moved an API endpoint from the Users service to the Videos service, and made it so if there is only one comment on a video it says 1 Comment instead of 1 Comments - Crazy right?!

View 3 commits

Attachment
1

Comments

ultraviolet.asdf
ultraviolet.asdf 13 days ago

Not pushed to demo yet, intending to change servers and enable custom video uploads soon

ultraviolet.asdf

iOS App!

I started working on an iOS app using swift!

This is my first time ever using swift, so it took quite a while.

Initially I tried using NativeScript Svelte, then React Native. Its pretty hard to get gRPC working with them, needing a proxy or something for the gRPC server, so I switched to swift instead.

Xcode (Apples IDE) doesn’t run on linux, so I had to install xtool and vscode/zed. I have to rebuild everytime I make a change, and the builds are pretty slow, but Swift is a really nice language and I may use it in the future

Attachment
0
ultraviolet.asdf

Shipped this project!

Hours: 44.5
Cookies: 🍪 1070
Multiplier: 24.06 cookies/hr

I built Watchtower, a Youtube clone. It is entirely self hostable.

I worked on it for over 92 hours before I found out about Flavortown.
As of now, I have coded over 44 hours worth of updates!

Note: Live streams and uploading videos are disabled in the demo. I do not have a GPU server, so videos would take days to process and analyse. Live streams would probably blow up the laptop I’m hosting everything on. You can still live chat though

Features

  • Transcoding: uploaded videos get transcoded to multiple resolutions (360p, 480p, 720p, 1080,1440p and 2160p). You can upload vertical videos and it will keep the aspect ratio
  • Thumbnail generation: Creates a storyboard image that allows you to seek through the video with a preview
  • Video Analyser: Videos are split into frames, frames are deduplicated and each frame is analysed for NSFW content
  • Live streams: You can stream from OBS to Watchtower. This uses nginx-rtmp. Authentication is managed by a golang server, approving or rejecting streams
  • Live chat: There is a live stream chat built using websockets
  • CDN: I built a CDN that manages permissions for videos, and proxies to the RTMP server so stream keys remain hidden
  • Admin dashboard: I wrote an admin dashboard with user/video analytics, it allows you to manage users, reports and appeals
  • Reports: Users can report videos and an admin can block reported videos
  • Appeals: Blocked videos can have an appeal requested by the owner, approved or rejected by an admin

Tech stack

  • The API is built using go with gRPC/Protobuf
  • The frontend is written with go, templ and htmx
  • The CDN is built with go
  • S3 (SeaweedFS) is used for storage
  • Postgres is used as the database
  • Valkey(redis) is used for the live chat
  • Gorse is used as a recommendation system
  • RabbitMQ is used as the message broker
  • The transcoder was built with Go + FFMPEG
  • The thumbnail generator was also built with Go + FFMPEG
  • The video_analyser was first built with go, then rewritten with Typescript (Bun). The package nsfwjs was used.
  • The analytics is written with go, and is run as a cronjob once a day, counting the number of users and videos

Development

I built a tool called devman specifically for this. It allows you to run multiple services from a configuration file. Each services can wait for other services to be online, so programs do not crash if something not up yet.
You can check it out on Codeberg

ultraviolet.asdf

Video Reporting

I finished video reporting, now admins can flag a reported video in the admin dashboard

Attachment
Attachment
0
ultraviolet.asdf

Moderation Appeal

You can now request an appeal if your video gets blocked.

There is a new page in the admin dashboard to view appeals

Admins can either reject or remove appeals

Rejecting will not allow the user to create another appeal

View The Code

Attachment
Attachment
Attachment
Attachment
Attachment
0
ultraviolet.asdf

Rewrite

I rewrote the video analyzer (NSFW detection) from Go to TypeScript, because the go package used for NSFW broke.
It might be slower, but at least it works

Can’t really have many screenshots for this update…

I also reduced the amount of things you need to install by using go tools,
where instead of installing the binary I run go get -tool and call it using go tool
More work for me, less work for someone trying to set this up themselves.

I also reinstalled my OS 2 times, so thats why this update took a while

You can view the changes on Codeberg

Attachment
0
ultraviolet.asdf

Live chat

I added chats to live streams! (you can chat even when the stream is offline
This was implemented using websockets (this is like the 8th microservice)

I made it so scrolling pauses the chat, so you can read messages.
The colour of the usernames are based on the hash of your username, I should probably let you pick a colour though.

0
ultraviolet.asdf

Live streams fix

I fixed live streams by writing a proxy to the stream server

Also did a few bug fixes
View The Changes

Attachment
1

Comments

ultraviolet.asdf
ultraviolet.asdf about 1 month ago

Haven’t pushed the fix to the demo, not sure if I will because handling live streams may crash my laptop

ultraviolet.asdf

Replaced dropzone.js with a custom upload script, so uploading matches the theme better
(4h of work because everything decided to break)
(ps don’t use RustFS, it is buggy and vibecoded)

View the code

Attachment
Attachment
0
ultraviolet.asdf

I added trending, and did a few other things, like improving security, working on a demo environment, improving code, fixing a bug and cleaning up processed thumbnails

View 5 changes

Attachment
0
ultraviolet.asdf

Admin Dashboard Improvements

I added a user management page that lists all users (with scrolling to load more) and allows flag management (Admin/Verified flags)

View the change

I should add search next

0
ultraviolet.asdf

Improved UX by redirecting back to profile page after deleting a video (with a refresh) so deleted videos don’t show after deletion
Also changed some endpoints to use proper http semantics

Attachment
Attachment
0
ultraviolet.asdf

I hid private/unprocessed videos in the recommended feed
Also had problems with atlas migrations which took hours to fix :)

Attachment
0
ultraviolet.asdf

I added a most popular sort option to the homepage of WatchTower.
I am planning to add a trending option as well.
I should probably remove some of the duplicated logic though and replace /videos/latest and /videos/popular with /videos/{sort_type}

Attachment
Attachment
0
ultraviolet.asdf

I added a “latest” sort option to my video sharing platform
I also fixed a bug where usernames wouldn’t show on recommended videos
Next up is sorting by popularity

Attachment
0