教程:向 Azure Functions 应用授予访问媒体服务帐户的权限
警告
Azure 媒体服务将于 2024 年 6 月 30 日停用。 有关详细信息,请参阅 AMS 停用指南。
假设你想让访问网站或应用程序的人知道你在广播工作室中的状态是“正在直播”。 可以使用媒体服务 API 确定媒体服务直播活动何时运行,但可能很难从嵌入式设备调用它。 可以改为使用 Azure Functions 为嵌入式设备公开 HTTP API。 然后,Azure Functions 便可调用媒体服务来获取直播活动的状态。
本教程使用 2020-05-01 媒体服务 API。
登录 Azure
要使用本文中的任何命令,首先必须登录到要使用的订阅。
登录 Azure。 使用此命令时,系统会提示你输入想要使用的订阅。
az login
设置订阅
使用此命令设置要使用的订阅。
使用 CLI 设置 Azure 订阅
在以下命令中,为媒体服务帐户提供想要使用的 Azure 订阅 ID。
az account set --subscription <subscriptionName>
先决条件
重要
强烈建议在学习本教程之前先完成通过命令行在 Azure 中创建 C# 函数快速入门。 这是因为其中包含的设置步骤与此处所需的步骤相同。 在该快速入门中,还可以使用作为本教程基础的简单示例。
资源名称
在开始之前,确定要创建的资源名称。 为这些资源命名时应使其易于识别为一组,尤其是在完成测试后不打算再使用它们。 许多资源类型的命名规则是不同的,因此最好始终采用全小写形式。 例如,“mediatest1rg”表示资源组名称,而“mediatest1stor”表示存储帐户名称。 对本文中的每个步骤使用相同的名称。
你将看到以下命令中引用了这些名称。 所需资源名称包括:
- myRG
- myStorageAccount
- myAmsAccount
- location
- myFunction: use "OnAir"
- myLiveEvent: use "live1"
- ipaddresses use: "0.0.0./32"
注意
上述连字符仅用于分隔引导词。 由于 Azure 服务中的命名资源不一致,因此在命名资源时请勿使用连字符。
用 00000000-0000-0000-0000000000 表示的任何内容都是资源的唯一标识符。 此值通常由 JSON 响应返回。 你应在记事本或其他文本编辑器中复制并粘贴 JSON 响应,因为这些响应将包含以后 CLI 命令所需的值。
此外,也不用创建区域名称。 区域名称由 Azure 确定。
列出 Azure 区域
如果不确定要使用的实际区域名称,请使用此命令获取列表:
使用此命令列出适用于你的帐户的区域。
az account list-locations --query "[].{DisplayName:displayName, Name:name}" -o table
序列
以下每个步骤都是按特定顺序完成的,因为你在序列的下一步中使用了来自 JSON 响应的一个或多个值。
创建存储帐户
你将创建的媒体服务帐户必须具有与之关联的存储帐户。 首先为媒体服务帐户创建存储帐户。 你将在后续步骤中使用 your-storage-account-name
。
使用 CLI 创建 Azure 存储帐户
使用以下命令创建一个 Azure 存储帐户。
若要创建存储帐户,必须先在某个位置创建一个资源组。
若要列出可用位置,请使用以下命令:
使用 CLI 列出可用位置
若要列出可用位置,请使用以下命令:
az account list-locations
使用 CLI 创建资源组
若要创建资源组,请使用以下命令:
az group create -n <resourceGroupName> --location chooseLocation
选择 SKU
还需要为存储帐户选择 SKU。 可以列出存储帐户。
从以下列表中选择 SKU:Standard_LRS、Standard_GRS、Standard_RAGRS、Premium_LRS。
- 将
myStorageAccount
更改为长度少于 24 个字符的唯一名称。 - 将
chooseLocation
更改为要使用的区域。 - 将
chooseSKU
更改为首选 SKU。
az storage account create -n <myStorageAccount> -g <resourceGroup> --location <chooseLocation> --sku <chooseSKU>
创建媒体服务帐户
现在创建媒体服务帐户。 查找 `
有关此命令的详细信息,请参阅 CLI 参考。
设置 Azure Functions
在本部分中,你将设置 Azure Functions。
获取代码
使用 Azure Functions 创建函数项目,并从 HTTP 模板检索代码。
func init MediaServicesLiveMonitor -dotnet
更改目录
请务必将工作目录更改为项目目录, 否则会出现错误。
cd .\MediaServicesLiveMonitor\
为函数命名
func new --name OnAir --template "HTTP trigger" --authlevel "anonymous"
配置函数项目
安装媒体服务和其他扩展
在终端窗口中运行 dotnet add package 命令,在项目中安装所需的扩展包。 以下命令安装媒体服务和 Azure 标识包。
dotnet add package Microsoft.Azure.Management.Media
dotnet add package Azure.Identity
编辑 OnAir.cs 代码
更改 OnAir.cs
文件。 将 subscriptionId
、resourceGroup
和 mediaServicesAccountName
变量更改为之前确定的变量。
using Azure.Core;
using Azure.Identity;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Management.Media;
using Microsoft.Azure.Management.Media.Models;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Rest;
using System.Threading.Tasks;
namespace MediaServicesLiveMonitor
{
public static class OnAir
{
[FunctionName("OnAir")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
if (string.IsNullOrWhiteSpace(name))
{
return new BadRequestObjectResult("Missing 'name' URL parameter");
}
var credential = new ManagedIdentityCredential();
var accessTokenRequest = await credential.GetTokenAsync(
new TokenRequestContext(
scopes: new string[] { "https://management.core.chinacloudapi.cn" + "/.default" }
)
);
ServiceClientCredentials credentials = new TokenCredentials(accessTokenRequest.Token, "Bearer");
var subscriptionId = "00000000-0000-0000-000000000000"; // Update
var resourceGroup = "<your-resource-group-name>"; // Update
var mediaServicesAccountName = "<your-media-services-account-name>"; // Update
var mediaServices = new AzureMediaServicesClient(credentials)
{
SubscriptionId = subscriptionId
};
var liveEvent = await mediaServices.LiveEvents.GetAsync(resourceGroup, mediaServicesAccountName, name);
if (liveEvent == null)
{
return new NotFoundResult();
}
return new OkObjectResult(liveEvent.ResourceState == LiveEventResourceState.Running ? "On air" : "Off air");
}
}
}
创建 Functions 应用
创建用于托管函数的 Functions 应用。 该名称与之前下载的名称相同,即 MediaServicesLiveMonitorApp
。
az functionapp create --resource-group <your-resource-group-name> --consumption-plan-location your-region --runtime dotnet --functions-version 3 --name MediaServicesLiveMonitorApp --storage-account mediatest3store --assign-identity "[system]"
在 JSON 响应中查找 principalId
:
{
...
"identity": {
//Note the principalId value for the following step
"principalId": "00000000-0000-0000-000000000000",
"tenantId": "00000000-0000-0000-000000000000",
"type": "SystemAssigned",
"userAssignedIdentities": null
}
...
向函数应用授予媒体服务帐户资源的访问权限
对于此请求:
assignee
是来自az functionapp create
的 JSON 响应中的principalId
scope
是来自az ams account create
的 JSON 响应中的id
。 请参阅上面的示例 JSON 响应。
az role assignment create --assignee 00000000-0000-0000-000000000000 --role "Media Services Account Administrator" --scope "/subscriptions/<the-subscription-id>/resourceGroups/<your-resource-group>/providers/Microsoft.Media/mediaservices/<your-media-services-account-name>"
发布函数
func azure functionapp publish MediaServicesLiveMonitorApp
验证
在浏览器中,转到函数 URL,例如:
https://mediaserviceslivemonitorapp.chinacloudsites.cn/api/onair?name=live1
这应会返回 404(未找到)错误,因为直播活动尚不存在。
创建直播活动
az ams live-event create --resource-group test3 --account-name mediatest3 --name live1 --streaming-protocol RTMP
在浏览器中,转到函数 URL,例如:
https://mediaserviceslivemonitorapp.chinacloudsites.cn/api/onair?name=live1
此时应会显示“停播”。
启动直播活动
如果启动直播活动,函数应会返回“正在直播”。
az ams live-event start live1
此函数可供任何人使用。 保护对 Azure Functions 的访问和接通“正在直播”灯不在本文档的讨论范围内。
清理资源
如果不打算使用已创建的资源,请删除资源组。
使用 CLI 删除资源组
az group delete --name <your-resource-group-name>