你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 .NET 的 Azure 远程渲染客户端库 - 版本 1.1.0

使用 Azure 远程渲染 (ARR) 服务可以在云中渲染高质量的交互式 3D 内容,并将其实时流式传输到 HoloLens 2 等设备。

此 SDK 提供将资产转换为运行时所需的格式以及管理远程呈现会话的生存期的功能。

注意:会话运行后,客户端应用程序将使用“运行时 SDK”之一连接到该会话。 这些 SDK 旨在最好地支持执行 3D 渲染的交互式应用程序的需求。 它们在 (.net 或 (C++) 中提供。

产品文档

入门

安装包

使用以下方法之一安装适用于 .NET 的 Azure 混合现实 ARR 客户端库。

从 Visual Studio 包管理器:

Install-Package Azure.MixedReality.RemoteRendering

从 .NET CLI

dotnet add package Azure.MixedReality.RemoteRendering

添加包引用:

<PackageReference Include="Azure.MixedReality.RemoteRendering" Version="1.0.0" />

先决条件

需要一个 Azure 订阅和一个 Azure 远程渲染帐户才能使用此包。

验证客户端

构造远程呈现客户端需要经过身份验证的帐户和远程呈现终结点。 对于在 eastus 区域中创建的帐户,帐户域的格式为“eastus.mixedreality.azure.com”。 有几种不同的身份验证形式:

  • 帐户密钥身份验证
    • 使用帐户密钥可以快速开始使用 Azure 远程渲染。 但是,在将应用程序部署到生产环境之前,我们建议你将应用更新为使用 Azure AD 身份验证。
  • Azure Active Directory (AD) 令牌身份验证
    • 如果你正在生成企业应用程序,并且你的公司使用 Azure AD 作为其标识系统,则你可以在应用中使用基于用户的 Azure AD 身份验证。 然后,使用现有的 Azure AD 安全组授予对 Azure 远程渲染帐户的访问权限。 还可以直接向组织中的用户授予访问权限。
    • 否则,我们建议从支持你的应用的 Web 服务获取 Azure AD 令牌。 建议对生产应用程序使用此方法,因为这可以避免在客户端应用程序中嵌入用于访问 Azure 空间定位点的凭据。

有关详细说明和信息,请参阅 此处

在下面的示例中,客户端是使用 remoteRenderingEndpoint Uri 对象构造的。 可用终结点对应于区域,终结点的选择决定了服务在其中执行其工作的区域。 示例为 https://remoterendering.eastus2.mixedreality.azure.com

注意:对于转换资产,最好选择靠近包含资产的存储的区域。

注意:对于呈现,强烈建议使用服务选择离设备最近的区域。 与服务器通信所需的时间会影响体验的质量。

使用帐户密钥身份验证进行身份验证

AccountKeyCredential使用 对象使用帐户标识符和帐户密钥进行身份验证:

AzureKeyCredential accountKeyCredential = new AzureKeyCredential(accountKey);

RemoteRenderingClient client = new RemoteRenderingClient(remoteRenderingEndpoint, accountId, accountDomain, accountKeyCredential);

使用 AAD 客户端机密进行身份验证

ClientSecretCredential使用 对象执行客户端机密身份验证。

TokenCredential credential = new ClientSecretCredential(tenantId, clientId, clientSecret, new TokenCredentialOptions
{
    AuthorityHost = new Uri($"https://login.microsoftonline.com/{tenantId}")
});

RemoteRenderingClient client = new RemoteRenderingClient(remoteRenderingEndpoint, accountId, accountDomain, credential);

使用设备代码身份验证对用户进行身份验证

DeviceCodeCredential使用 对象执行设备代码身份验证。

Task deviceCodeCallback(DeviceCodeInfo deviceCodeInfo, CancellationToken cancellationToken)
{
    Debug.WriteLine(deviceCodeInfo.Message);
    Console.WriteLine(deviceCodeInfo.Message);
    return Task.FromResult(0);
}

TokenCredential credential = new DeviceCodeCredential(deviceCodeCallback, tenantId, clientId, new TokenCredentialOptions
{
    AuthorityHost = new Uri($"https://login.microsoftonline.com/{tenantId}"),
});

RemoteRenderingClient client = new RemoteRenderingClient(remoteRenderingEndpoint, accountId, accountDomain, credential);

有关使用设备代码身份验证流的详细信息,请参阅 此处

使用 DefaultAzureCredential 进行交互式身份验证

DefaultAzureCredential 对象与 结合使用 includeInteractiveCredentials: true ,以使用默认交互式身份验证流:

TokenCredential credential = new DefaultAzureCredential(includeInteractiveCredentials: true);

RemoteRenderingClient client = new RemoteRenderingClient(remoteRenderingEndpoint, accountId, accountDomain, credential);

使用静态访问令牌进行身份验证

可以将混合现实访问令牌作为AccessToken以前从 混合现实 STS 服务检索到的令牌传递,以便与 混合现实 客户端库一起使用:

// GetMixedRealityAccessTokenFromWebService is a hypothetical method that retrieves
// a Mixed Reality access token from a web service. The web service would use the
// MixedRealityStsClient and credentials to obtain an access token to be returned
// to the client.
AccessToken accessToken = GetMixedRealityAccessTokenFromWebService();

RemoteRenderingClient client = new RemoteRenderingClient(remoteRenderingEndpoint, accountId, accountDomain, accessToken);

关键概念

RemoteRenderingClient

RemoteRenderingClient是用于访问 RemoteRenderingService 的客户端库。 它提供了创建和管理资产转换和呈现会话的方法。

示例

转换简单资产

我们假设已按照 对客户端进行身份验证 部分中所述构造 RemoteRenderingClient。 以下代码片段介绍如何请求转换位于给定 URI 的 Blob 容器根目录中的“box.fbx”。

    AssetConversionInputOptions inputOptions = new AssetConversionInputOptions(storageUri, "box.fbx");
    AssetConversionOutputOptions outputOptions = new AssetConversionOutputOptions(storageUri);
    AssetConversionOptions conversionOptions = new AssetConversionOptions(inputOptions, outputOptions);

    // A randomly generated GUID is a good choice for a conversionId.
    string conversionId = Guid.NewGuid().ToString();

    AssetConversionOperation conversionOperation = client.StartConversion(conversionId, conversionOptions);

输出文件将放在输入资产旁边。

转换更复杂的资产

资产可以引用其他文件,Blob 容器可以包含属于许多不同资产的文件。 在此示例中,我们展示了如何使用前缀来组织 Blob,以及如何转换资产以考虑该组织。 假设 中的 inputStorageUri Blob 容器包含许多文件,包括“Bicycle/bicycle.gltf”、“Bicycle/bicycle.bin”和“Bicycle/saddleTexture.jpg”。 (因此前缀“自行车”非常类似于文件夹。) 我们希望转换 gltf,以便它可以访问共享前缀的其他文件,而无需转换服务访问任何其他文件。 为了保持整洁,我们还希望将输出文件写入其他存储容器,并指定一个通用前缀:“ConvertedBicycle”。 代码如下所示:

    AssetConversionInputOptions input = new AssetConversionInputOptions(inputStorageUri, "bicycle.gltf")
    {
        BlobPrefix = "Bicycle"
    };
    AssetConversionOutputOptions output = new AssetConversionOutputOptions(outputStorageUri)
    {
        BlobPrefix = "ConvertedBicycle"
    };
    AssetConversionOptions conversionOptions = new AssetConversionOptions(inputOptions, outputOptions);

    string conversionId = Guid.NewGuid().ToString();

    AssetConversionOperation conversionOperation = client.StartConversion(conversionId, conversionOptions);

注意:如果输入选项中提供了前缀,则假定输入文件参数相对于该前缀。 这同样适用于输出选项中的输出文件参数。

在资产转换完成时获取输出

转换资产可能需要几秒钟到几小时的时间。 此代码使用现有的 conversionOperation 并定期轮询,直到转换完成或失败。 默认轮询周期为 10 秒。 请注意,conversionOperation 可以从现有转换和客户端的 conversionId 构造。

    AssetConversion conversion = conversionOperation.WaitForCompletionAsync().Result;
    if (conversion.Status == AssetConversionStatus.Succeeded)
    {
        Console.WriteLine($"Conversion succeeded: Output written to {conversion.Output.OutputAssetUri}");
    }
    else if (conversion.Status == AssetConversionStatus.Failed)
    {
        Console.WriteLine($"Conversion failed: {conversion.Error.Code} {conversion.Error.Message}");
    }

列出转换

可以使用 方法获取有关转换 getConversions 的信息。 此方法可能会返回尚未开始的转换、正在运行的转换和已完成的转换。 在此示例中,我们仅列出在最后一天开始的成功转换的输出 URI。

    foreach (var conversion in client.GetConversions())
    {
        if ((conversion.Status == AssetConversionStatus.Succeeded) && (conversion.CreatedOn > DateTimeOffset.Now.AddDays(-1)))
        {
            Console.WriteLine($"output asset URI: {conversion.Output.OutputAssetUri}");
        }
    }

创建会话

我们假设已按照 对客户端进行身份验证 部分中所述构造 RemoteRenderingClient。 以下代码片段介绍如何请求启动新的呈现会话。

    RenderingSessionOptions options = new RenderingSessionOptions(TimeSpan.FromMinutes(30), RenderingServerSize.Standard);

    // A randomly generated GUID is a good choice for a sessionId.
    string sessionId = Guid.NewGuid().ToString();

    StartRenderingSessionOperation startSessionOperation = client.StartSession(sessionId, options);

    RenderingSession newSession = startSessionOperation.WaitForCompletionAsync().Result;
    if (newSession.Status == RenderingSessionStatus.Ready)
    {
        Console.WriteLine($"Session {sessionId} is ready.");
    }
    else if (newSession.Status == RenderingSessionStatus.Error)
    {
        Console.WriteLine($"Session {sessionId} encountered an error: {newSession.Error.Code} {newSession.Error.Message}");
    }

延长会话的租用时间

如果会话接近其最长租用时间,但你想要使其保持活动状态,则需要调用 以增加其最长租用时间。 此示例演示如何查询当前属性,并在租约即将到期时延长租约。

注意:运行时 SDK 也提供此功能,在许多典型方案中,你将使用它们来扩展会话租约。

    RenderingSession currentSession = client.GetSession(sessionId);

    if (currentSession.MaxLeaseTime - DateTimeOffset.Now.Subtract(currentSession.CreatedOn.Value) < TimeSpan.FromMinutes(2))
    {
        TimeSpan newLeaseTime = currentSession.MaxLeaseTime.Value.Add(TimeSpan.FromMinutes(30));

        UpdateSessionOptions longerLeaseSettings = new UpdateSessionOptions(newLeaseTime);

        client.UpdateSession(sessionId, longerLeaseSettings);
    }

列出会话

可以使用 方法获取有关会话 getSessions 的信息。 此方法可能会返回尚未启动的会话和已就绪的会话。

    foreach (var properties in client.GetSessions())
    {
        if (properties.Status == RenderingSessionStatus.Starting)
        {
            Console.WriteLine($"Session \"{properties.SessionId}\" is starting.");
        }
        else if (properties.Status == RenderingSessionStatus.Ready)
        {
            Console.WriteLine($"Session \"{properties.SessionId}\" is ready at host {properties.Host}");
        }
    }

停止会话

以下代码将停止具有给定 ID 的正在运行的会话。

    client.StopSession(sessionId);

故障排除

有关 Azure 远程渲染的一般故障排除建议,请参阅 docs.microsoft.com 的远程渲染疑难解答页

如果无法发出请求,客户端方法将引发异常。 但是,在转换和会话的情况下,请求可以成功,但请求的操作可能不会成功。 在这种情况下,不会引发异常,但可以检查返回的对象以了解所发生的情况。

如果转换中的资产无效,则转换操作将返回一个 AssetConversion 对象,该对象的状态为“失败”,并带有包含详细信息的 RemoteRenderingServiceError。 转换服务能够处理文件后, <会将 assetName.result.json> 文件写入输出容器。 如果输入资产无效,则该文件将包含问题的更详细说明。

同样,有时请求会话时,会话最终会处于错误状态。 startSessionOperation 方法将返回一个 RenderingSession 对象,但该对象将具有“错误”状态,并带有包含详细信息的 RemoteRenderingServiceError。

后续步骤

贡献

本项目欢迎贡献和建议。 大多数贡献要求你同意贡献者许可协议 (CLA),并声明你有权(并且确实有权)授予我们使用你的贡献的权利。 有关详细信息,请访问 https://cla.microsoft.com

提交拉取请求时,CLA 机器人将自动确定你是否需要提供 CLA,并相应地修饰 PR(例如标签、注释)。 直接按机器人提供的说明操作。 只需使用 CLA 对所有存储库执行一次这样的操作。

此项目采用了 Microsoft 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。