Sharpcaster 3.0.0
dotnet add package Sharpcaster --version 3.0.0
NuGet\Install-Package Sharpcaster -Version 3.0.0
<PackageReference Include="Sharpcaster" Version="3.0.0" />
<PackageVersion Include="Sharpcaster" Version="3.0.0" />
<PackageReference Include="Sharpcaster" />
paket add Sharpcaster --version 3.0.0
#r "nuget: Sharpcaster, 3.0.0"
#:package Sharpcaster@3.0.0
#addin nuget:?package=Sharpcaster&version=3.0.0
#tool nuget:?package=Sharpcaster&version=3.0.0
SharpCaster
SharpCaster is a cross-platform toolkit for communicating with Google Chromecast devices. It includes:
- C# SDK (NuGet): A library for .NET apps to discover, connect, launch apps, and control media on Chromecast devices.
- Sharpcaster Console (CLI): A cross‑platform command-line app for controlling Chromecast from your terminal, distributed via Chocolatey and Homebrew.
C# SDK supports .NET Standard 2.0 and .NET 9 (including Native AOT). Sharpcaster console is built with Native AOT for fast startup, low memory usage and doesn't require .NET installed, works on Windows, macOS, and Linux.
Table of Contents
- Features
- Installation
- Quick Start
- Comprehensive Examples
- Media Queue Management
- Volume Control
- Event Handling
- Custom Chromecast Channels
- Troubleshooting
- Contributing
- License
Features
✅ Device Discovery: Automatic discovery of Chromecast devices on your local network using mDNS
✅ Media Control: Complete media playback control (play, pause, stop, seek, volume)
✅ Queue Management: Support for media queues with navigation (next, previous, shuffle, repeat)
✅ Application Management: Launch and manage Chromecast applications
✅ Custom Channels: Extensible architecture for custom Chromecast channels
✅ Cross-Platform: Compatible with .NET Standard 2.0 and .NET 9
✅ AOT Ready: Full support for Native AOT compilation in .NET 9
✅ Async/Await: Modern async programming model throughout
✅ Event-Driven: Rich event system for real-time status updates
Installation
C# SDK (NuGet)
Install via NuGet Package Manager:
Install-Package SharpCaster
Or via .NET CLI:
dotnet add package SharpCaster
Sharpcaster Console (CLI)
Control Chromecast devices from your terminal.
- Homebrew (macOS/Linux):
brew tap Tapanila/sharpcaster
brew install sharpcaster
- Chocolatey (Windows):
choco install sharpcaster --pre
After installation, run sharpcaster
for interactive mode, or use direct commands like:
sharpcaster list
sharpcaster "Living Room TV" play "https://example.com/video.mp4" --title "Sample"
For full CLI usage and examples, see SharpCaster.Console/README.md
.
Quick Start
1. Discover and Connect to Chromecast
using Sharpcaster;
using Sharpcaster.Models;
using Sharpcaster.Models.Media;
// Discover Chromecast devices
var locator = new ChromecastLocator();
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token;
var chromecasts = await locator.FindReceiversAsync(cancellationToken);
if (!chromecasts.Any())
{
Console.WriteLine("No Chromecast devices found");
return;
}
// Connect to first found device
var chromecast = chromecasts.First();
var client = new ChromecastClient();
await client.ConnectChromecast(chromecast);
Console.WriteLine($"Connected to {chromecast.Name}");
2. Launch Application and Play Media
// Launch the default media receiver app
await client.LaunchApplicationAsync("CC1AD845"); // Default Media Receiver
// Create and load media
var media = new Media
{
ContentUrl = "https://commondatastorage.googleapis.com/gtv-videos-bucket/CastVideos/mp4/DesigningForGoogleCast.mp4",
ContentType = "video/mp4",
Metadata = new MediaMetadata
{
Title = "Sample Video",
SubTitle = "A demonstration video"
}
};
var mediaStatus = await client.MediaChannel.LoadAsync(media);
Console.WriteLine($"Media loaded: {mediaStatus.PlayerState}");
Comprehensive Examples
Complete Media Player Example
public class ChromecastMediaPlayer
{
private ChromecastClient _client;
private ChromecastReceiver _device;
public async Task<bool> ConnectAsync(string deviceName = null)
{
try
{
var locator = new ChromecastLocator();
var devices = await locator.FindReceiversAsync(CancellationToken.None);
_device = deviceName != null
? devices.FirstOrDefault(d => d.Name.Contains(deviceName))
: devices.FirstOrDefault();
if (_device == null) return false;
_client = new ChromecastClient();
await _client.ConnectChromecast(_device);
// Subscribe to events
_client.MediaChannel.StatusChanged += OnMediaStatusChanged;
_client.Disconnected += OnDisconnected;
return true;
}
catch (Exception ex)
{
Console.WriteLine($"Connection failed: {ex.Message}");
return false;
}
}
public async Task PlayVideoAsync(string url, string title = null)
{
await _client.LaunchApplicationAsync("CC1AD845"); // Default Media Receiver
var media = new Media
{
ContentUrl = url,
ContentType = GetContentType(url),
Metadata = new MediaMetadata
{
Title = title ?? Path.GetFileNameWithoutExtension(url),
MetadataType = MetadataType.Movie
}
};
await _client.MediaChannel.LoadAsync(media);
}
public async Task PlayAudioAsync(string url, string title = null, string artist = null)
{
await _client.LaunchApplicationAsync("CC1AD845");
var media = new Media
{
ContentUrl = url,
ContentType = GetContentType(url),
Metadata = new MusicTrackMetadata
{
Title = title ?? Path.GetFileNameWithoutExtension(url),
Artist = artist,
MetadataType = MetadataType.MusicTrack
}
};
await _client.MediaChannel.LoadAsync(media);
}
private void OnMediaStatusChanged(object sender, MediaStatus status)
{
Console.WriteLine($"Media Status: {status.PlayerState} - {status.CurrentTime:F1}s");
}
private void OnDisconnected(object sender, EventArgs e)
{
Console.WriteLine("Disconnected from Chromecast");
}
private static string GetContentType(string url)
{
var extension = Path.GetExtension(url).ToLower();
return extension switch
{
".mp4" => "video/mp4",
".mp3" => "audio/mpeg",
".wav" => "audio/wav",
".webm" => "video/webm",
_ => "video/mp4"
};
}
}
Media Queue Management
SharpCaster supports advanced queue operations for playlist-style media playback:
// Create a media queue
var queueItems = new[]
{
new QueueItem
{
Media = new Media
{
ContentUrl = "https://example.com/song1.mp3",
ContentType = "audio/mpeg",
Metadata = new MusicTrackMetadata { Title = "Song 1", Artist = "Artist 1" }
}
},
new QueueItem
{
Media = new Media
{
ContentUrl = "https://example.com/song2.mp3",
ContentType = "audio/mpeg",
Metadata = new MusicTrackMetadata { Title = "Song 2", Artist = "Artist 2" }
}
}
};
// Load queue with repeat mode
await client.MediaChannel.QueueLoadAsync(queueItems, 0, RepeatModeType.ALL);
// Navigate through queue
await client.MediaChannel.QueueNextAsync(); // Next track
await client.MediaChannel.QueuePrevAsync(); // Previous track
// Get queue information
var itemIds = await client.MediaChannel.QueueGetItemIdsAsync();
var items = await client.MediaChannel.QueueGetItemsAsync(itemIds);
Volume Control
// Get current volume
var status = await client.ReceiverChannel.GetChromecastStatusAsync();
Console.WriteLine($"Current volume: {status.Volume.Level:P0}");
// Set volume (0.0 to 1.0)
await client.ReceiverChannel.SetVolumeAsync(0.5f);
// Mute/unmute
await client.ReceiverChannel.SetMutedAsync(true);
await client.ReceiverChannel.SetMutedAsync(false);
Event Handling
SharpCaster provides rich event support for real-time updates:
// Media events
client.MediaChannel.StatusChanged += (sender, status) =>
{
Console.WriteLine($"Player State: {status.PlayerState}");
Console.WriteLine($"Current Time: {status.CurrentTime}s");
Console.WriteLine($"Duration: {status.Media?.Duration}s");
};
// Connection events
client.Disconnected += (sender, args) =>
{
Console.WriteLine("Connection lost to Chromecast");
};
// Application events
client.ReceiverChannel.StatusChanged += (sender, status) =>
{
foreach (var app in status.Applications ?? [])
{
Console.WriteLine($"Running app: {app.DisplayName} ({app.AppId})");
}
};
Custom Chromecast Channels
Create custom channels for specialized applications:
public class CustomGameChannel : ChromecastChannel
{
public CustomGameChannel(ILogger<CustomGameChannel> logger)
: base("custom.game", logger) { }
public async Task SendGameCommandAsync(string command, object data)
{
var message = new { type = command, data = data };
await SendAsync(JsonSerializer.Serialize(message));
}
protected override async Task OnMessageReceivedAsync(string message, string messageType)
{
// Handle custom game messages
var gameMessage = JsonSerializer.Deserialize<GameMessage>(message);
// Process game-specific logic
}
}
// Register and use custom channel
var gameChannel = new CustomGameChannel(logger);
client.RegisterChannel(gameChannel);
You can also reverse engineer existing channels:
- In Chrome, go to
chrome://net-export/
- Select 'Include raw bytes (will include cookies and credentials)'
- Click 'Start Logging to Disk'
- Cast from your favorite web app
- Stop logging and open the log in netlog-viewer
- Search for
type:SOCKET
and find familiar JSON data - Collect the exchanged JSON
- Create a new class inheriting from
ChromecastChannel
and implement your logic
Troubleshooting
Common Issues and Solutions
Device Discovery Issues:
// Increase discovery timeout for slow networks
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token;
var devices = await locator.FindReceiversAsync(cancellationToken);
// Manually specify device if discovery fails
var manualDevice = new ChromecastReceiver
{
Name = "My Chromecast",
DeviceUri = new Uri("http://192.168.1.100"),
Port = 8009
};
Connection Timeouts:
// Enable logging for debugging
var loggerFactory = LoggerFactory.Create(builder =>
builder.AddConsole().SetMinimumLevel(LogLevel.Debug));
var client = new ChromecastClient(loggerFactory);
Media Loading Failures:
- Ensure media URLs are publicly accessible
- Verify correct
ContentType
is specified - Check that the Chromecast supports the media format
- Use HTTPS URLs when possible
Network Issues:
- Ensure device is on the same network as Chromecast
- Check firewall settings (port 8009 must be accessible)
- Verify mDNS/Bonjour is enabled on the network
Error Handling Best Practices
try
{
await client.MediaChannel.LoadAsync(media);
}
catch (TimeoutException)
{
Console.WriteLine("Request timed out - check network connection");
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"Invalid operation: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
}
Demo
Supported Platforms
- .NET Standard 2.0 - Maximum compatibility across .NET implementations
- .NET 9 - Latest features including Native AOT support
- Compatible with: .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5+, Xamarin, Unity
Contributing
We welcome contributions! Here's how you can help:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
Development Setup
git clone https://github.com/Tapanila/SharpCaster.git
cd SharpCaster
dotnet restore
dotnet build
dotnet test
Testing
Tests require a physical Chromecast device on the network:
dotnet test
Some of the tests may require few tries to pass due to network conditions.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Google.Protobuf (>= 3.32.0)
- Microsoft.CSharp (>= 4.7.0)
- Microsoft.Extensions.DependencyInjection (>= 9.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.8)
- System.Text.Json (>= 9.0.8)
- Zeroconf (>= 3.7.16)
-
net9.0
- Google.Protobuf (>= 3.32.0)
- Microsoft.CSharp (>= 4.7.0)
- Microsoft.Extensions.DependencyInjection (>= 9.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.8)
- System.Text.Json (>= 9.0.8)
- Zeroconf (>= 3.7.16)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Sharpcaster:
Package | Downloads |
---|---|
SharpCaster.Console
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated | |
---|---|---|---|
3.0.0 | 113 | 8/29/2025 | |
2.0.3 | 281 | 7/19/2025 | |
2.0.2 | 194 | 7/19/2025 | |
2.0.1 | 129 | 7/17/2025 | |
2.0.0 | 150 | 7/9/2025 | |
2.0.0-beta1 | 1,366 | 12/27/2024 | |
1.2.4 | 154 | 7/9/2025 | |
1.2.3 | 475 | 12/3/2024 | |
1.2.2 | 301 | 8/30/2024 | |
1.2.1 | 198 | 8/12/2024 | |
1.2.1-alpha | 135 | 8/12/2024 | |
1.2.0 | 188 | 7/21/2024 | |
1.1.18 | 165 | 7/20/2024 | |
1.1.17 | 141 | 7/18/2024 | |
1.1.16 | 134 | 7/18/2024 | |
1.1.15 | 135 | 7/18/2024 | |
1.1.14 | 140 | 7/16/2024 | |
1.1.3 | 169 | 7/15/2024 | |
1.1.2 | 149 | 7/8/2024 | |
1.1.1 | 150 | 7/3/2024 | |
1.1.0 | 129 | 7/3/2024 | |
1.0.8 | 1,864 | 2/27/2023 | |
1.0.7 | 845 | 2/27/2023 | |
1.0.6 | 893 | 2/8/2023 | |
1.0.5 | 1,547 | 5/2/2022 | |
1.0.4 | 1,275 | 3/29/2022 | |
1.0.3 | 1,303 | 2/18/2022 | |
1.0.0 | 1,217 | 2/12/2022 | |
0.4.0 | 7,657 | 5/21/2017 | |
0.4.0-pre | 1,606 | 5/21/2017 | |
0.3.5 | 1,943 | 4/1/2017 | |
0.3.5-pre | 1,576 | 1/23/2017 | |
0.3.4 | 1,935 | 1/11/2017 | |
0.3.4-pre | 1,640 | 1/11/2017 | |
0.3.3-pre | 1,620 | 1/1/2017 | |
0.3.2 | 1,969 | 11/25/2016 | |
0.3.1 | 1,933 | 9/30/2016 | |
0.3.1-pre | 1,585 | 9/30/2016 | |
0.3.0 | 1,855 | 9/8/2016 | |
0.3.0-pre | 1,573 | 9/8/2016 | |
0.2.0-pre | 1,649 | 8/31/2016 | |
0.1.7-pre2 | 1,606 | 8/18/2016 | |
0.1.7-pre | 1,623 | 8/14/2016 | |
0.1.6 | 1,873 | 8/2/2016 | |
0.1.5 | 1,903 | 6/2/2016 | |
0.1.4 | 1,890 | 3/22/2016 | |
0.1.3 | 1,862 | 3/9/2016 | |
0.1.2 | 1,816 | 3/4/2016 | |
0.1.1 | 2,154 | 2/13/2016 | |
0.0.0 | 166 | 8/12/2024 |
See https://github.com/Tapanila/SharpCaster/releases for release notes