![]() |
VOOZH | about |
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" />Directory.Packages.props
<PackageReference Include="Sharpcaster" />Project file
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.0Install as a Cake Addin
#tool nuget:?package=Sharpcaster&version=3.0.0Install as a Cake Tool
π .NET Build Status
π NuGet Status
π Chocolatey
π Homebrew Tap
SharpCaster is a cross-platform toolkit for communicating with Google Chromecast devices. It includes:
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.
β
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
Install via NuGet Package Manager:
Install-Package SharpCaster
Or via .NET CLI:
dotnet add package SharpCaster
Control Chromecast devices from your terminal.
brew tap Tapanila/sharpcaster
brew install sharpcaster
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.
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}");
// 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}");
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"
};
}
}
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);
// 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);
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})");
}
};
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:
chrome://net-export/type:SOCKET and find familiar JSON dataChromecastChannel and implement your logicDevice 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:
ContentType is specifiedNetwork Issues:
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}");
}
We welcome contributions! Here's how you can help:
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)git clone https://github.com/Tapanila/SharpCaster.git
cd SharpCaster
dotnet restore
dotnet build
dotnet test
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.
This project is licensed under the MIT License - see the file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 1 NuGet packages that depend on Sharpcaster:
| Package | Downloads |
|---|---|
|
SharpCaster.Console
Package Description |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0 | 5,702 | 8/29/2025 |
| 2.0.3 | 534 | 7/19/2025 |
| 2.0.2 | 369 | 7/19/2025 |
| 2.0.1 | 301 | 7/17/2025 |
| 2.0.0 | 306 | 7/9/2025 |
| 2.0.0-beta1 | 1,545 | 12/27/2024 |
| 1.2.4 | 290 | 7/9/2025 |
| 1.2.3 | 680 | 12/3/2024 |
| 1.2.2 | 440 | 8/30/2024 |
| 1.2.1 | 339 | 8/12/2024 |
| 1.2.1-alpha | 225 | 8/12/2024 |
| 1.2.0 | 331 | 7/21/2024 |
| 1.1.18 | 960 | 7/20/2024 |
| 1.1.17 | 277 | 7/18/2024 |
| 1.1.16 | 269 | 7/18/2024 |
| 1.1.15 | 274 | 7/18/2024 |
| 1.1.14 | 272 | 7/16/2024 |
| 1.1.3 | 320 | 7/15/2024 |
| 1.1.2 | 291 | 7/8/2024 |
| 0.0.0 | 328 | 8/12/2024 |
See https://github.com/Tapanila/SharpCaster/releases for release notes