-
-
Notifications
You must be signed in to change notification settings - Fork 55
Getting started
Installing the packages and wiring them into an app. Fifteen minutes, and at the end of it Hello world proves the native half actually loaded.
If you want the shortest possible path: create the project, add the package, do the one platform-specific step your platform needs, then run Hello world.
-
.NET 10 SDK.
dotnet --versionshould report10.0.400or later. -
MAUI workload, if you are building a MAUI app:
dotnet workload install maui. - Whatever your platform normally needs to build and deploy — Android SDK and a JDK, Xcode and a Mac for iOS and Mac Catalyst, the Windows 10 SDK for Windows.
Three platform requirements fail silently if you miss them — a hang with no message, or a restore error that does not name this package. They are covered in Platform prerequisites, and each one is repeated in place below.
| reference | what it gives you | |
|---|---|---|
| I have my own signalling and UI | WebRTCme |
the API and the bindings |
| I want a call app without writing plumbing | WebRTCme.Middleware |
the above, plus managers, a video tile and a connection layer |
The middleware depends on the API package, so referencing it brings both. Never reference a
binding directly — they are inside WebRTCme.
WebAssembly only. Blazor Server and Blazor Hybrid are not supported.
dotnet new blazorwasm -n HelloWebRtc
cd HelloWebRtc
dotnet add package WebRTCme --version 26.9.21Add WebRTCme.Middleware too if you want the middleware:
dotnet add package WebRTCme.Middleware --version 26.9.21This one is silent if you miss it. The Blazor binding is JSInterop over the browser's own WebRTC API, and the JavaScript half ships as a static web asset. Without the tag nothing works and nothing says why.
In wwwroot/index.html, before _framework/blazor.webassembly.js:
<script src="_content/WebRTCme/JsInterop.js"></script>Coming from 2.0.0? The path changed. It used to be
_content/WebRTCme.Bindings.Blazor/JsInterop.js.
Only needed if you are using WebRTCme.Middleware. The API package on its own needs no
registration at all — see step 4.
using WebRTCme;
using WebRTCme.Middleware;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
var middleware = CrossWebRtcMiddlewareBlazor.Current;
builder.Services.AddSingleton(middleware.WebRtc);
builder.Services.AddSingleton(middleware);
builder.Services.AddBlazorMiddleware();
await builder.Build().RunAsync();Blazor is the one platform where Window() needs an argument: the browser's IJSRuntime, which
a component gets by injection and a plain class has no way to reach.
@inject IJSRuntime JsRuntime
@code {
protected override void OnInitialized()
{
var window = CrossWebRtc.Current.Window(JsRuntime);
var pc = window.RTCPeerConnection(new RTCConfiguration { IceServers = [] });
}
}The other four platforms ignore the argument, so passing it unconditionally is correct everywhere. That is why every sample here passes it.
One project, four platforms: Android, iOS, Mac Catalyst and Windows.
dotnet new maui -n HelloWebRtc
cd HelloWebRtc
dotnet add package WebRTCme.Middleware --version 26.9.21Your restore will fail without this, and the error will not mention WebRTCme:
error NU1605: Detected package downgrade: Microsoft.Maui.Controls from 10.0.101 to 10.0.20
The packages depend on Microsoft.Maui.Controls 10.0.101. Your MAUI workload's implicit reference
is whatever that workload bundles, which is usually lower, and NuGet calls the difference a
downgrade and refuses. Name the versions yourself, exactly as NU1605 instructs:
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.101" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="10.0.101" />
</ItemGroup>This is not optional and it is not discoverable until the restore fails. Keep it in step when you upgrade WebRTCme — Releases states the version each release wants.
Skip this and your app hangs at startup with no error at all.
WebRTCme is a MAUI library on Windows, so it brings the Windows App SDK, which injects a
bootstrapper into the module constructor of anything referencing it. If that bootstrapper cannot
find a matching Windows App Runtime framework package it does not throw — it blocks. Your app
stops before Main, having written nothing to any log.
Your development machine already has the runtime, because Visual Studio's MAUI workload installs it. A clean machine does not. The simplest fix is to carry it:
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
</PropertyGroup>A packaged (MSIX) app does not need this — the dependency is declared and the installer supplies
it. An unpackaged app, which is what plain dotnet publish produces, does. The alternative is
shipping WindowsAppRuntimeInstall.exe and asking users to run it.
Full story in Platform prerequisites.
In MauiProgram.cs:
using WebRTCme;
using WebRTCme.Middleware;
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureMauiHandlers(handlers =>
{
// Only needed if you use the middleware's video tile.
handlers.AddHandler(typeof(Media), typeof(MediaHandler));
});
var middleware = CrossWebRtcMiddlewareMaui.Current;
builder.Services.AddSingleton(middleware.WebRtc);
builder.Services.AddSingleton(middleware);
builder.Services.AddMauiMiddleware();
return builder.Build();
}Using WebRTCme alone? Drop the handler line and all three service registrations —
CrossWebRtc.Current needs no container.
Not needed for Hello world, which uses a data channel and touches no hardware —
but needed the moment you call GetUserMedia.
Android, in Platforms/Android/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />iOS and Mac Catalyst, in Platforms/iOS/Info.plist and Platforms/MacCatalyst/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Allow video camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Allow microphone access</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Local network access is required to reach the signalling server and connect calls.</string>Restoring and compiling proves less than you would like. NuGet falls back: a net10.0-android
project with no Android slice resolves lib/net10.0/ instead and compiles perfectly, because the
common API is identical across slices. What it would not have is any Android binding — and nothing
says so until the app runs on a phone and finds nothing behind the interface.
So the check that means something is a running one. Hello world negotiates a real peer connection in about sixty lines, with no signalling server, no camera and no network. If it prints a message, then on your platform the native half loaded, SDP marshalled both ways, ICE candidates survived the round trip, and DTLS and SCTP completed.
| Hello world | Prove it works, then turn it into a real call |
| The unified API | What the whole surface looks like |
| Connection | Let the middleware do the signalling — peer-to-peer or through an SFU |
| Demo apps | Two complete apps, in the repository |
| Troubleshooting | When one of the above did not go as written |
Start here
The stack
- WebRTCnative
- Bindings
- The unified API
- Middleware
- Connection
- · Signaling (mesh)
- · MediaSoup (SFU)
- Demo apps
Reference
When it breaks