ShowShark Release Notes v2026.03.23

Overview

At first I thought it'd be pretty simple to implement downloads and offline playback. I'd need a workaround for the realtime pacing that happens on the server while transcoding (ie, transcode as fast as possible), and I'd need to save it to "disk" (client side) for offline playback. What I discovered is that my early decision to use PCM audio for everything had a meaningful downside: the audio portion of the data stream accounted for 5/6ths (or more!) of the data transfer. Video, the seemingly more complex portion, was a tiny fraction. I only noticed this because I decided to write the audio packets to one file and the video frames to another file, so that I could independently access each "stream" during playback (batching audio packets and video frames to reduce messaging overhead would otherwise mean that I'd need to do extra buffering on the client to better mux the two streams when writing them to a single file). Anyway, like I said, 80% of the data was just audio (and associated overhead).

I'm still happy I started with PCM audio for everything because it reduced the complexity of getting things working initially – audio/video synchronization in particular. Starting from a solid foundation and iterating on that (adding AAC audio) was still challenging, but do-able, and WAY easier than trying to debug synchronization issues while wondering if AAC encoding / decoding was a contributing factor.

I've more-or-less got ShowShark where I want it to be for basic usefulness with just tweaks and minor features on the horizon at the moment. I've got a ridiculous feature list, but I'm going to be judicious in deciding on feature creep here.

Web Client

  • ShowShark Web Client for browser-based media playback. Connect to your server from any desktop browser without installing a native app. Includes full video and audio playback, server authentication, and thumbnail browsing
  • Safari support with a certificate trust UX flow and cross-browser video/audio decoding. H.264 streams use dual AVCC/Annex B mode for compatibility across Chrome, Firefox, and Safari
  • Secure transport with HTTPS and WSS for all web client connections
  • ShowShark Server converted to a menu bar app that runs in the system tray instead of the Dock. The server starts automatically at launch regardless of window visibility, freeing up Dock and Cmd-Tab space
  • Menu bar popover shows per-service status with ports (WSS, WS, HTTP, HLS), active streams, connected clients, and quick action buttons. Hover highlighting and dismiss-on-click replicate native macOS menu behavior
  • Show Main Window option in the popover for accessing the full server UI when needed
  • Launch at Login toggle in Settings for starting the server when your Mac boots
  • Suppress main window on subsequent launches so the server starts silently in the menu bar after the initial setup

YouTube Library Support

  • YouTube library scanning imports locally downloaded YouTube content (via yt-dlp) as browsable shows and episodes. Each YouTube channel becomes a show with episodes, complete with metadata, thumbnails, and tags
  • Local yt-dlp metadata parsing reads .info.json sidecar files as the primary metadata source, eliminating YouTube API dependency when local files are present. The API remains as a fallback
  • Description cleanup replaces {BR} markers and strips control characters from YouTube descriptions during import for clean, readable text
  • Metadata Doctor support for YouTube content, allowing manual metadata corrections on imported YouTube shows and episodes

Remote Connectivity

  • Per-account tailnet isolation so each Apple account gets its own isolated network namespace.
  • Per-namespace client state directories prevent node identity conflicts when a client connects to servers on different accounts
  • Tailnet connection status displayed in the Server StatusView with a green/gray indicator and IP address
  • Automatic tailnet reconnection when a remote connection drops, the client resets the node, re-joins the tailnet, and reconnects without manual intervention
  • Stale tailnet node recovery with automatic reset when connections fail, preventing dead SOCKS5 proxy reuse

Offline Downloads

  • Offline video downloads with local playback support for watching content without a server connection
  • AAC audio codec support for downloads, raw-frame playback, and music playback
  • Downloads grouped by content topic in the Downloads view for easier browsing
  • Race condition fix preventing corrupt offline packages when fast encoders finish before the file writer catches up
  • tvOS downloads stored in Caches directory per Apple guidelines for re-downloadable content

Playlists & Favorites

  • Playlists and Favorites system with full client-server support. Create custom playlists, add movies, shows, episodes, albums, artists, and songs. A dedicated Favorites playlist provides quick access to your most-loved content
  • Heart icon for playlist actions across all detail and playback views. A filled heart indicates the item belongs to at least one playlist, updating immediately when playlists change
  • Actor playlist support in ActorBrowseView with a Play button for playing an actor's filmography and adding their works to playlists
  • Actor profile photos displayed in playlist and favorites grid items

Music & Audio

  • Music mini player for background audio playback on all platforms. Dismissing the music player keeps audio playing with a compact mini player bar showing the current track, progress, and playback controls
  • Now Playing toolbar button with stop/open options. Tapping presents a dialog to either open the full player or stop background playback entirely
  • Audio spectrum visualizer with real-time frequency analysis using Metal and Canvas rendering backends. Includes Falling Pulses and Neon Rain visualizer styles alongside existing options
  • Track list sheet for browsing and selecting tracks during collection-based audio playback
  • Startup burst mode for GStreamer audio sessions to reduce music playback startup latency
  • Audio-only EOS fix preventing the last few seconds of music from being clipped at the end of playback

Channels

  • Per-channel consecutive episode toggle for channels mixing TV shows with movies. Disabling back-to-back prevention allows natural episode flow without forcing a movie between every episode
  • Channel thumbnails refresh periodically to show the currently airing program instead of a stale image
  • Channel filter summary now shows movie/show titles instead of the generic "No filters configured" text
  • Channel delete moved to editor toolbar with a confirmation dialog, removing the destructive action from list row swipe gestures

Streaming & Playback

  • Deinterlacing support for interlaced video content (e.g., 1080i broadcasts), automatically detecting and deinterlacing as needed
  • FLV container and Sorenson Spark (FLV1) codec support for playback of legacy Flash video files
  • ASF/WMV container support for playback of .wmv, .wma, and .asf files
  • H.264 software decoder fallback when hardware vtdec_hw encounters incompatible streams, falling back gracefully instead of failing
  • Video PTS discontinuity absorption to prevent pacing freezes when streams contain timestamp jumps
  • Audio-only video containers (e.g., .mp4 files with only an audio track) now route to the audio playback handler instead of failing in the video player
  • GStreamer plugin preloading at startup to survive Xcode rebuilds that change the app code signature
  • EOS buffer drain ensures all buffered frames are displayed before completing playback, preventing the last few seconds from being cut off
  • ABR controller rewrite with buffer-based AIMD algorithm and server-side send timing for more responsive bitrate adaptation
  • Vorbis audio playback fix for WebM and Matroska containers where vorbisparse blocked preroll indefinitely, preventing playback of VP8/Vorbis media files

Library & Scanning

  • Location type annotations with type-aware library scanning. Locations can be marked as Movies, TV Shows, Music, or YouTube, and the scanner uses the appropriate strategy for each type
  • Nested location skip during directory enumeration to prevent cross-type scanning when one location is inside another
  • Duplicate location path prevention when adding or editing locations
  • Improved episode detection for obfuscated filenames and non-standard naming conventions
  • Files with NULL duration are now updated on rescan instead of being permanently stuck, fixing channels that reported "No media available" for affected shows
  • File-type-specific placeholder icons in the media browser grid when thumbnails are unavailable
  • Punctuation and diacritic-insensitive library search so searches like "cant" match "Can't" and "cafe" matches "Café"

Device Management

  • Device type identification using hardware model identifiers resolved to marketing names (e.g., "iPhone 16 Pro", "Apple TV 4K") with device-appropriate SF Symbol icons
  • Device admin roles with an edit sheet for toggling admin status, viewing known IP addresses, and deleting devices
  • User role in login response returning "admin" or "user" based on the device's admin flag
  • mDNS-based device name resolution for generic iOS and tvOS device names that otherwise show as "iPhone" or "Apple TV"

Server

  • Sparkle auto-update integration for ShowShark Server with a "Check for Updates" menu item
  • Sparkle auto-update for ShowShark Remote with automatic update checks
  • Photo library TCC verification detects when the Photos entitlement is broken despite reporting authorized, disabling photo features and showing a warning instead of silently failing
  • Stale client connection detection via ping liveness monitoring, cleaning up ghost connections that no longer respond
  • Unauthenticated connections hidden from the StatusView connections list, filtering out diagnostic probes and failed handshakes
  • Metadata Doctor for manually correcting metadata on movies, shows, and episodes with TMDB ID validation and OMDB enrichment
  • Library delete with file metadata assignment and improved episode parsing for library management
  • Throttled cleanup scan progress to prevent SwiftUI layout crashes from rapid progress updates

Client UI

  • Buffering progress bars replace static text labels with visual progress indicators
  • About links open in-app instead of launching the system browser
  • Server list spinner now appears immediately when tapping a server to connect
  • Cast member cards top-aligned in movie and show detail views for consistent layout
  • Media browser resets on server tap for immediate UI feedback when switching servers
  • Minimum OS versions lowered to x.0 releases for broader device compatibility
  • Sign in with Apple now captures and displays user full names
  • Privacy policy and end user license agreement added

tvOS

  • tvOS track list rows are now properly focusable with correct horizontal content margins
  • tvOS spectrum visualizer back button correctly closes the visualizer instead of exiting the entire player
  • tvOS episode navigation fix preventing the wrong episode from playing when navigating from a playback modal

Bug Fixes

  • Black screen fix when opening video while background audio is playing, caused by a race condition between stopping the mini player and starting video playback
  • Music channel restart fix when reopening the player from the mini player; existing playback sessions are now preserved instead of being torn down and restarted
  • Mini player disappearing fix during track transitions on macOS and iPad
  • Data race crash fix in DevicesManager on concurrent logins
  • Data race crash fix in ChannelsManager.photoCollectionCache
  • MainActor isolation crash fix in MediaGridView history section
  • TailscaleKit crash fix caused by corrupted filch log buffer files after unclean shutdowns
  • Unbounded memory growth fix in DownloadSessionRegistry for non-download sessions
  • Unbounded audio buffer fix preventing memory retention after playback stops
  • Metal Particle Storm visualizer fix for rendering mostly off-screen
  • Radial visualizer fix for bars disappearing after one full rotation
  • Audio playback navigation fix for music channels using the wrong navigation coordinator
  • Playlist addition fix preventing albums from being added instead of individual songs from the audio playback view
  • Port number display fix using Text(verbatim:) to prevent locale-aware thousand separators in port numbers (e.g., "18,080")