.NET APIs to manage LiveKit Access Tokens, Webhook and Server APIs. Use it with a .NET backend. It is build with netstandard2.0
as target framework, so the SDK can be used in all versions of .NET.
The SDK implements:
- Access Tokens
- Webhooks
- Room Service
- Egress Service
- Ingress Service
- SIP Service
- Agent Service
dotnet add package Livekit.Server.Sdk.Dotnet
using Livekit.Server.Sdk.Dotnet;
var token = new AccessToken("yourkey", "yoursecret")
.WithIdentity("participant-identity")
.WithName("participant-name")
.WithGrants(new VideoGrants{ RoomJoin = true, Room = "room-name" })
.WithAttributes(new Dictionary<string, string> { { "mykey", "myvalue" } })
.WithTtl(TimeSpan.FromHours(1));
var jwt = token.ToJwt();
By default, a token expires after 6 hours. You may override this by calling method WithTtl
in the AccessToken
object, just as shown in the example above.
It's possible to customize the permissions of each participant. See more details at access tokens guide.
RoomServiceClient
is a Twirp-based client that provides management APIs to LiveKit. You can connect it to your LiveKit endpoint. See service apis for a list of available APIs.
using Livekit.Server.Sdk.Dotnet;
RoomServiceClient client = new RoomServiceClient(
"https://my.livekit.instance",
"yourkey",
"yoursecret"
);
// List rooms
var listRoomsRequest = new ListRoomsRequest();
var listRoomsResponse = await client.ListRooms(listRoomsRequest);
Room[] rooms = listRoomsResponse.Rooms.ToArray();
// List participants
var listParticipantsRequest = new ListParticipantsRequest { Room = "room-name" };
var listParticipantsResponse = await client.ListParticipants(listParticipantsRequest);
ParticipantInfo[] participants = listParticipantsResponse.Participants.ToArray();
// Mute published track
var mutePublishedTrackRequest = new MuteRoomTrackRequest
{
Room = "room-name",
Identity = "participant-identity",
TrackSid = "track-sid",
Muted = true,
};
await client.MutePublishedTrack(mutePublishedTrackRequest);
// Remove participant
var removeParticipantRequest = new RoomParticipantIdentity
{
Room = "room-name",
Identity = "participant-identity",
};
await client.RemoveParticipant(removeParticipantRequest);
// Delete room
var deleteRoomRequest = new DeleteRoomRequest { Room = "room-name" };
await client.DeleteRoom(deleteRoomRequest);
EgressServiceClient
is a .NET client to EgressService. Refer to docs for more usage examples.
using Livekit.Server.Sdk.Dotnet;
EgressServiceClient client = new EgressServiceClient(
"https://my.livekit.instance",
"yourkey",
"yoursecret"
);
// Starting a room composite to S3
var s3request = new RoomCompositeEgressRequest { RoomName = "room-name" };
s3request.FileOutputs.Add(
new EncodedFileOutput
{
FileType = EncodedFileType.Mp4,
Filepath = "my-recording.mp4",
S3 = new S3Upload
{
AccessKey = "aws-access-key",
Secret = "aws-access-secret",
Region = "bucket-region",
Bucket = "my-bucket",
},
}
);
EgressInfo s3Egress = await client.StartRoomCompositeEgress(s3request);
// Starting a track composite to RTMP
var rtmpRequest = new TrackCompositeEgressRequest
{
RoomName = "room-name",
AudioTrackId = "TR_XXXXXXXXXXXX",
VideoTrackId = "TR_XXXXXXXXXXXX",
StreamOutputs =
{
new StreamOutput
{
Protocol = StreamProtocol.Rtmp,
Urls = { "rtmp://url1", "rtmps://url2" },
},
},
};
EgressInfo rtmpEgress = await client.StartTrackCompositeEgress(rtmpRequest);
IngressServiceClient
is a .NET client to IngressService. Refer to docs for more usage examples.
using Livekit.Server.Sdk.Dotnet;
IngressServiceClient client = new IngressServiceClient(
"https://my.livekit.instance",
"yourkey",
"yoursecret"
);
// Publish an ingress participant from URL
var urlRequest = new CreateIngressRequest
{
RoomName = "room-name",
ParticipantIdentity = "ingress-participant",
ParticipantMetadata = "ingress-metadata",
ParticipantName = "ingress-name",
InputType = IngressInput.UrlInput,
Url = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
};
IngressInfo ingress = await client.CreateIngress(urlRequest);
// Publish an ingress participant from RTMP
var rtmpRequest = new CreateIngressRequest
{
RoomName = "room-name",
ParticipantIdentity = "ingress-participant",
ParticipantMetadata = "ingress-metadata",
ParticipantName = "ingress-name",
InputType = IngressInput.RtmpInput,
Video = new IngressVideoOptions
{
Preset = IngressVideoEncodingPreset.H2641080P30Fps3LayersHighMotion,
},
};
ingress = await client.CreateIngress(rtmpRequest);
// List ingresses
var response = await client.ListIngress(new ListIngressRequest());
IngressInfo[] ingresses = response.Items.ToArray();
// Delete an ingress
await client.DeleteIngress(new DeleteIngressRequest { IngressId = ingress.IngressId });
SipServiceClient
is a .NET client to SipService. Refer to docs for more usage examples.
using Livekit.Server.Sdk.Dotnet;
SipServiceClient client = new SipServiceClient(
"https://my.livekit.instance",
"yourkey",
"yoursecret"
);
// Create SIP inbound trunk
var inRequest = new CreateSIPInboundTrunkRequest
{
Trunk = new SIPInboundTrunkInfo
{
Name = "Demo inbound trunk",
Numbers = { "+1234567890" },
AllowedNumbers = { "+11111111", "+22222222" },
AllowedAddresses = { "1.1.1.0/24" },
},
};
SIPInboundTrunkInfo inboundTrunk = await client.CreateSIPInboundTrunk(inRequest);
// Create SIP outbound trunk
var outRequest = new CreateSIPOutboundTrunkRequest
{
Trunk = new SIPOutboundTrunkInfo
{
Name = "Demo outbound trunk",
Address = "my-test-trunk.com",
Numbers = { "+1234567890" },
AuthUsername = "username",
AuthPassword = "password",
},
};
SIPOutboundTrunkInfo outboundTrunk = await client.CreateSIPOutboundTrunk(outRequest);
// Create dispatch rule
var ruleRequest = new CreateSIPDispatchRuleRequest
{
Name = "Demo dispatch rule",
Metadata = "Demo dispatch rule metadata",
Rule = new SIPDispatchRule
{
DispatchRuleDirect = new SIPDispatchRuleDirect { RoomName = "room-name", Pin = "1234" },
},
};
SIPDispatchRuleInfo dispatchRule = await client.CreateSIPDispatchRule(ruleRequest);
The .NET SDK also provides helper functions to decode and verify webhook callbacks. While verification is optional, it ensures the authenticity of the message. See webhooks guide for details.
LiveKit POSTs to webhook endpoints with Content-Type: application/webhook+json
. Please ensure your server is able to receive POST body with that MIME.
using Livekit.Server.Sdk.Dotnet;
var webhookReceiver = new WebhookReceiver("yourkey", "yoursecret");
// In order to use the validator, WebhookReceiver must have access to the raw POSTed string
// This example uses "ASP.NET Core Web SDK" to handle the webhook request from LiveKit Server
// (https://learn.microsoft.com/en-us/aspnet/core/razor-pages/web-sdk?view=aspnetcore-8.0)
app.MapPost("/webhook-endpoint", async (HttpRequest request) => {
var body = new StreamReader(request.Body);
string postData = await body.ReadToEndAsync();
var authHeader = request.Headers["Authorization"].First();
WebhookEvent webhookEvent = webhookReceiver.Receive(postData, authHeader);
// Here you have available the WebhookEvent object
Console.Out.WriteLine(webhookEvent);
return Results.Ok();
});
You may store credentials in environment variables. If api-key or api-secret is not passed in when creating an AccessToken
, RoomServiceClient
(or any other service client) the values in the following env vars will be used:
LIVEKIT_API_KEY
LIVEKIT_API_SECRET
At LivekitApi.Example you can find a sample application using livekit-server-sdk-dotnet.
Pre-requisites:
- protoc
go install github.com/seanpfeifer/twirp-gen/cmd/protoc-gen-twirpcs@latest
Generate proto files:
./generate_proto.sh
Build the SDK:
dotnet build
Run all tests:
dotnet test
Run unit tests:
dotnet test --filter "Category=Unit"
Run integration tests (they automatically launch necessary services as Docker containers with Testcontainers):
dotnet test --filter "Category=Integration"
- Tests are automatically run in GitHub Actions after each commit, thanks to this workflow.
- A new version is published to NuGet after a new release is created in GitHub, thanks to this workflow.
It is necessary the NuGet tool.
First of all, configure the local NuGet repository in the NuGet configuration file. This is by default %appdata%\NuGet\NuGet.Config
in Windows and ~/.nuget/NuGet/NuGet.Config
Mac/Linux. Simply add line <add key="Local" value="/home/YOUR_USER/.private_nuget" />
if it does not already exist:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="Local" value="/home/YOUR_USER/.private_nuget" />
</packageSources>
</configuration>
In this way we are configuring our local NuGet repository in the ~/.private_nuget
directory.
Then pack and install the package in the local repository. Run these commands at the root of the project livekit-server-sdk-dotnet
:
dotnet pack -c Debug -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
# Delete existing previous version just in case
nuget delete Livekit.Server.Sdk.Dotnet 1.0.0 -Source ~/.private_nuget/ -np
# Install the package in the local NuGet repository
nuget add "$PWD"/bin/Debug/Livekit.Server.Sdk.Dotnet.1.0.0.nupkg -Source ~/.private_nuget/
Once the NuGet package is installed in the local repository, you can add it to any local dotnet project with:
# Run this command at the root of the project where you want to add the NuGet package
dotnet add package Livekit.Server.Sdk.Dotnet
You can reset the local repository at any time with these commands:
dotnet nuget locals all --clear
dotnet restore
Note: all this process is automated in the
build_local.sh
script. Tested in Unix systems.
To upgrade the version of the livekit/protocol
Git submodule:
cd protocol
git checkout COMMIT_HASH/TAG/BRANCH
cd ..
git add protocol
git commit "Update livekit/protocol version"
git push
Then it may be necessary to re-generate the proto files to actually reflect the changes in livekit/protocol:
./generate_proto.sh
Then try packaging the SDK to test the validity of the changes in the protocol:
dotnet pack -c Debug -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
This command may throw an error if there are breaking changes in the protocol, as the SDK is configured in strict mode for package validation. The way to overcome these breaking changes is running the package command with option -p:GenerateCompatibilitySuppressionFile=true
to generate file CompatibilitySuppressions.xml
:
dotnet pack -c Debug -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg -p:GenerateCompatibilitySuppressionFile=true
This compatibility suppression file will allow packaging and publishing the SDK even with breaking changes. Once the new version is available in NuGet, the only thing left is to update in file LivekitApi.csproj
property <PackageValidationBaselineVersion>X.Y.Z</PackageValidationBaselineVersion>
to the new version (so the new reference for breaking changes is this new version), and delete CompatibilitySuppressions.xml
(as it is no longer needed).