Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Azure Media Services DRM与第三方统一流媒体服务器的集成_Azure_Drm_Azure Media Services_Exoplayer - Fatal编程技术网

Azure Media Services DRM与第三方统一流媒体服务器的集成

Azure Media Services DRM与第三方统一流媒体服务器的集成,azure,drm,azure-media-services,exoplayer,Azure,Drm,Azure Media Services,Exoplayer,概述 我们正在构建一个音乐流应用程序,主要针对Android设备。其主要目的是销售音乐订阅,同时保护我们为最终用户提供的媒体资产,因此DRM解决方案是我们基础设施的核心。我们的设置如下所示: 核心组成部分: 带有Exoplayer的Android移动应用程序 作为流媒体服务器的统一流媒体服务器 Azure媒体服务用于DRM服务 Azure Media Services Sdk中的密钥生成实用程序 以下是我们采取的步骤: 步骤1:编码 我们使用ffmpeg将各种媒体资源编码为不同的mp4比特率输出

概述

我们正在构建一个音乐流应用程序,主要针对Android设备。其主要目的是销售音乐订阅,同时保护我们为最终用户提供的媒体资产,因此DRM解决方案是我们基础设施的核心。我们的设置如下所示:

核心组成部分:

  • 带有Exoplayer的Android移动应用程序
  • 作为流媒体服务器的统一流媒体服务器
  • Azure媒体服务用于DRM服务
  • Azure Media Services Sdk中的密钥生成实用程序
  • 以下是我们采取的步骤:

    步骤1:编码

    我们使用ffmpeg将各种媒体资源编码为不同的mp4比特率输出:

    • 256kbps
    • 192kbps
    • 128kbps
    • 96kbps
    • 64kbps
    步骤2:加密 转换媒体资产后,我们将对转换后的媒体资产执行两步编码过程

    • 首先,我们使用以下示例输出运行AZURE.NET SDK以生成密钥:
    关键字:nb:kid:UUID:fae1ab22-cd13-44f8-a746-0d7dd3a31645

    键值:MVEP833L3JMUANVTY3JUQ==

    PlayReady URL:

    Widevine URL:

    身份验证策略:nb:ckpid:UUID:15ec2f3f-4ad9-49be-9f89-b5431bc3dec1

    这将为我们生成以下项目:密钥ID、内容密钥、身份验证策略和许可证URL

    我们注意到,在使用Azure.NET SDK时,有一个令牌限制策略选项,该选项负责通过SWT或JWT令牌为许可证生成令牌保护,并带有一系列选项。因为我们不需要令牌保护,所以我们将SDK设置为使用开放授权策略颁发许可证。我们在下面突出显示了为实现此目的而修改的代码行,以供参考:

    由于ExoPlayer只能在Android TV上播放PlayReady,我们只能申请Widevine许可证

    • 然后,我们使用统一流媒体mp4split工具用上面从Azure.NET SDK突出显示的信息加密我们的媒体资产。下面显示了为Widevine许可证加密资产的命令,并提供了有关该命令的更多详细信息
    有关命令的注释:

    我们需要将KEY_ID和CONTENT_KEY转换为十六进制值,然后才能在mp4split命令中使用它们:

    UUID的键号:fae1ab22-cd13-44f8-a746-0d7dd3a31645变为
    22ABE1FA13CDF844A7460D7DD3A31645

    MVEP833L3JMUANVTY3JUQ==的内容键变为
    315129F37DCBDE399468DBD3CB7254B9

    我们仍然不知道从Azure.NET SDK得到的响应中PSSH值是多少。统一流媒体文档说明如下:

    02-07 12:58:58.458 16454-5913/com.google.android.exoplayer2.demo   E/OMXMaster: A component of name 'OMX.qcom.audio.decoder.aac' already exists,  ignoring this one.
        02-07 12:59:02.892 16454-5811/com.google.android.exoplayer2.demo E/ExoPlayerImplInternal: Renderer error.
        com.google.android.exoplayer2.ExoPlaybackException
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.shouldWaitForKeys(MediaCodecRenderer.java:709)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:650)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:490)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:464)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:300)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:168)
        at android.os.HandlerThread.run(HandlerThread.java:61)
        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40)
        Caused by: com.google.android.exoplayer2.drm.DrmSession$DrmSessionException: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 400
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onError(DefaultDrmSessionManager.java:594)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeysError(DefaultDrmSessionManager.java:589)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeyResponse(DefaultDrmSessionManager.java:549)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.access$900(DefaultDrmSessionManager.java:49)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostResponseHandler.handleMessage(DefaultDrmSessionManager.java:669)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:168) 
        at android.os.HandlerThread.run(HandlerThread.java:61) 
        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40) 
        Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 400
        at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:212)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:101)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:81)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:75)
        at com.google.android.exoplayer2.util.Util.toByteArray(Util.java:118)
        at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executePost(HttpMediaDrmCallback.java:106)
        at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executeKeyRequest(HttpMediaDrmCallback.java:91)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostRequestHandler.handleMessage(DefaultDrmSessionManager.java:692)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:168)
        at android.os.HandlerThread.run(HandlerThread.java:61)
        02-07 12:59:02.896 16454-16454/com.google.android.exoplayer2.demo E/EventLogger: playerFailed [7.76]
        com.google.android.exoplayer2.ExoPlaybackException
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.shouldWaitForKeys(MediaCodecRenderer.java:709)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:650)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:490)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:464)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:300)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:168)
        at android.os.HandlerThread.run(HandlerThread.java:61)
        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40)
        Caused by: com.google.android.exoplayer2.drm.DrmSession$DrmSessionException: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 400
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onError(DefaultDrmSessionManager.java:594)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeysError(DefaultDrmSessionManager.java:589)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeyResponse(DefaultDrmSessionManager.java:549)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.access$900(DefaultDrmSessionManager.java:49)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostResponseHandler.handleMessage(DefaultDrmSessionManager.java:669)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:168) 
        at android.os.HandlerThread.run(HandlerThread.java:61) 
        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40) 
        Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 400
        at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:212)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:101)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:81)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:75)
        at com.google.android.exoplayer2.util.Util.toByteArray(Util.java:118)
        at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executePost(HttpMediaDrmCallback.java:106)
        at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executeKeyRequest(HttpMediaDrmCallback.java:91)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostRequestHandler.handleMessage(DefaultDrmSessionManager.java:692)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:168)
        at android.os.HandlerThread.run(HandlerThread.java:61)
    
    许可证服务器提供的DRM特定数据(Widevine PSSH数据)。 可以是Base64字符串,也可以是包含已解码Base64数据的文件。文件名必须包含“.”

    请注意,LA_URL(许可证获取URL)不会在“pssh”框中显示,通常在支持Winevine模块化的DASH播放器中硬编码。建议的设置是使用正确的URL

    我们正在寻求帮助,以便从我们收到的Azure.NETSDK输出中找出PSSH数据是什么。与此同时,我们一直在使用AUTH_POLICY_ID(转换为Base64)作为mp4split命令中的PSSH

    当我们将以上所有内容放在一起时,我们使用的mp4split脚本将变成:

    #!/bin/bash
          KID=22ABE1FA13CDF844A7460D7DD3A31645
          CEK=315129F37DCBDE399468DBD3CB7254B9
          LAURL="https://music.keydelivery.mediaservices.windows.net/Widevine/?     KID=fae1ab22-cd13-44f8-a746-0d7dd3a31645"
          PSSH="Py/sFdlKvkmfibVDG8PewQ=="
    
          mp4split --license-key=usp/license.key -o musicfile.ism \
            --mpd.inline_drm \
            --widevine.key=${KID}:${CEK} \
            --widevine.license_server_url=${LAURL} \
            --widevine.drm_specific_data=${PSSH} \
            musicfile-64kbps.mp4
    
          aws s3 cp musicfiles.ism s3://output-bucket/
          aws s3 cp musicfiles-64kbps.mp4 s3://output-bucket/
    
    注:

  • 对于上述命令,我们正在为64kps比特率mp4音乐文件生成具有Widevine许可证加密的ism清单文件
  • --许可证密钥用于统一流媒体高级产品
  • AWS S3命令用于将生成的ism和相关mp4 64kps比特率文件上载到AWS S3存储桶
  • 完成此过程后,下一步是与ExoPlayer集成

    步骤3:流媒体

    一旦我们将.ism及其相关mp4文件上传到S3存储桶中,移动应用程序将使用以下详细信息访问流并播放它:

    {
            "name": "Music Tests",
            "uri": "http://mozart.musicfiles.com/auth/media/musicfiles.ism/.mpd",
            "drm_scheme": "widevine",
            "drm_license_url":      "https://music.keydelivery.mediaservices.windows.net/Widevine/?KID=fae1ab22-cd13-44f8-a746-0d7dd3a31645"
          }
    
    其中:

    URI-是我们的统一流媒体服务器端点 DRM_许可证_URI-是我们的Azure.NET SDK提供的widevine服务器url

    在上传、编码和加密媒体资产后,我们会在这一阶段出现错误。Android应用程序中的错误如下:

    02-07 12:58:58.458 16454-5913/com.google.android.exoplayer2.demo   E/OMXMaster: A component of name 'OMX.qcom.audio.decoder.aac' already exists,  ignoring this one.
        02-07 12:59:02.892 16454-5811/com.google.android.exoplayer2.demo E/ExoPlayerImplInternal: Renderer error.
        com.google.android.exoplayer2.ExoPlaybackException
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.shouldWaitForKeys(MediaCodecRenderer.java:709)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:650)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:490)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:464)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:300)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:168)
        at android.os.HandlerThread.run(HandlerThread.java:61)
        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40)
        Caused by: com.google.android.exoplayer2.drm.DrmSession$DrmSessionException: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 400
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onError(DefaultDrmSessionManager.java:594)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeysError(DefaultDrmSessionManager.java:589)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeyResponse(DefaultDrmSessionManager.java:549)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.access$900(DefaultDrmSessionManager.java:49)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostResponseHandler.handleMessage(DefaultDrmSessionManager.java:669)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:168) 
        at android.os.HandlerThread.run(HandlerThread.java:61) 
        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40) 
        Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 400
        at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:212)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:101)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:81)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:75)
        at com.google.android.exoplayer2.util.Util.toByteArray(Util.java:118)
        at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executePost(HttpMediaDrmCallback.java:106)
        at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executeKeyRequest(HttpMediaDrmCallback.java:91)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostRequestHandler.handleMessage(DefaultDrmSessionManager.java:692)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:168)
        at android.os.HandlerThread.run(HandlerThread.java:61)
        02-07 12:59:02.896 16454-16454/com.google.android.exoplayer2.demo E/EventLogger: playerFailed [7.76]
        com.google.android.exoplayer2.ExoPlaybackException
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.shouldWaitForKeys(MediaCodecRenderer.java:709)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:650)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:490)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:464)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:300)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:168)
        at android.os.HandlerThread.run(HandlerThread.java:61)
        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40)
        Caused by: com.google.android.exoplayer2.drm.DrmSession$DrmSessionException: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 400
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onError(DefaultDrmSessionManager.java:594)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeysError(DefaultDrmSessionManager.java:589)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeyResponse(DefaultDrmSessionManager.java:549)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.access$900(DefaultDrmSessionManager.java:49)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostResponseHandler.handleMessage(DefaultDrmSessionManager.java:669)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:168) 
        at android.os.HandlerThread.run(HandlerThread.java:61) 
        at com.google.android.exoplayer2.util.PriorityHandlerThread.run(PriorityHandlerThread.java:40) 
        Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 400
        at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:212)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:101)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:81)
        at com.google.android.exoplayer2.upstream.DataSourceInputStream.read(DataSourceInputStream.java:75)
        at com.google.android.exoplayer2.util.Util.toByteArray(Util.java:118)
        at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executePost(HttpMediaDrmCallback.java:106)
        at com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executeKeyRequest(HttpMediaDrmCallback.java:91)
        at com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostRequestHandler.handleMessage(DefaultDrmSessionManager.java:692)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:168)
        at android.os.HandlerThread.run(HandlerThread.java:61)
    
    Azure媒体服务中的错误代码在此处表示以下响应代码400:

    400错误请求请求包含无效信息,请求无效 由于以下原因之一而被拒绝:

    -指定了不受支持的API版本。最新 版本,请参阅媒体服务REST API开发的设置-API 未指定媒体服务的版本。有关如何 指定API版本,请参阅使用连接到媒体服务 媒体服务RESTAPI。注

    如果您使用.NET或Java SDK连接到媒体服务, 每当您尝试执行某些操作时,都会为您指定API版本 对媒体服务采取行动

    • 已指定未定义的属性。属性名称在错误消息中。仅限作为给定对象成员的属性 可以指定实体。请参阅Azure媒体服务REST API参考 获取实体及其属性的列表

      • 指定了无效的属性值。属性名称在错误消息中。有关有效的属性类型,请参见上一链接 以及他们的价值观
    • 缺少属性值,该值是必需的。
      • 指定的URL的一部分包含错误值
    • 试图更新WriteOnce属性
    • 试图创建一个作业,该作业的输入资产具有未指定或无法确定的主资产文件
    • 有人试图掩盖事实
      GET https://music.keydelivery.mediaservices.windows.net/Widevine/?KID=fae1ab22-cd13-44f8-a746-0d7dd3a31645
      
      <?xml version="1.0" encoding="utf-8"?>
      <Error>
      <Message>License challenge is missing from the request body.</Message>
      <Code>NoLicenseChallenge</Code>
      </Error>