zoukankan      html  css  js  c++  java
  • Azure直播活动资源转成MP4并下载到本地

       记录一下最近遇到一个需求要把通过Azure媒体服务的直播活动产生的资源,转成可播放的MP4格式并下载到本地。文档参考了Azure Media Service Explore下载工具的源码才实现这个功能。

     通过Azure Media Service Explore工具下载直播生成视频文档地址:https://docs.azure.cn/zh-cn/articles/azure-operations-guide/media-services/aog-media-services-qa-download-the-live-generated-video-files

     工具下载地址:https://github.com/Azure/Azure-Media-Services-Explorer/releases/tag/v5.2.0.4

    以下是实现的代码(C#)

    IAzureMediaServicesClient client = CreateMediaServicesClient(subId);

     /// <summary>
    /// 
    /// </summary>
    /// <param name="subscriptionId">订阅ID</param>
    /// <returns></returns>

    private IAzureMediaServicesClient CreateMediaServicesClient(string subscriptionId)
    {
    var credentials = GetCredentialsAsync().Result;

    return new AzureMediaServicesClient(new Uri(_restApiEndpoint), credentials)
    {
    SubscriptionId = subscriptionId,
    };
    }


    private async Task<ServiceClientCredentials> GetCredentialsAsync()
    {

    ClientCredential clientCredential = new ClientCredential(_clientId, _clientSecret);
    return await ApplicationTokenProvider.LoginSilentAsync(_tenantId, clientCredential, ActiveDirectoryServiceSettings.AzureChina);
    }

    /// <summary>
    /// 获取资产信息
    /// </summary>
    /// <param name="ResourceGroup">资源组</param>
    /// <param name="AccountName">媒体服务</param>
    /// <param name="assetsName">资产名</param>
    /// <returns></returns>
    public Asset GetAsset(string resourceGroup, string accountName, string assetsName)
    {
    return client.Assets.Get(resourceGroup, accountName, assetsName);
    }

    /// <summary>
    /// 创建和获取转换编解码器
    /// </summary>
    /// <param name="resourceGroup">资源组</param>
    /// <param name="accountName">媒体服务</param>
    /// <param name="transformName">转换名称</param>
    /// <returns></returns>
    private Transform CreateAndGetCopyCodecTransformIfNeeded(string resourceGroup, string accountName, string transformName)
    {
    Transform myTransform = null;

    bool found = true;
    try
    {
    myTransform = GetTransformAsync(resourceGroup, accountName, transformName);
    }
    catch
    {
    found = false;
    }
    if (!found | myTransform == null)
    {
    TransformOutput[] outputs;


    outputs = new TransformOutput[]
    {
    new TransformOutput(CustomCopyPreset),
    };

    myTransform = client.Transforms.CreateOrUpdate(resourceGroup, accountName, transformName, outputs, null);

    }

    return myTransform;
    }

    /// <summary>
    /// 获取Job信息
    /// </summary>
    /// <param name="ResourceGroup"></param>
    /// <param name="AccountName"></param>
    /// <param name="transformName"></param>
    /// <param name="jobName"></param>
    /// <returns></returns>
    public Job GetJob(string ResourceGroup, string AccountName, string transformName, string jobName)
    {
    return client.Jobs.Get(ResourceGroup, AccountName, transformName, jobName);
    }

    /// <summary>
    /// 创建Job
    /// </summary>
    /// <param name="resourceGroup">资源组</param>
    /// <param name="accountName">媒体服务</param>
    /// <param name="transformName"></param>
    /// <param name="asset">直播产生的视频资产</param>
    /// <param name="jobName">任务名称</param>
    /// <param name="start">任务开始时间</param>
    /// <param name="end">任务结束时间</param>
    /// <param name="outputAsset">转换完成后的资产</param>
    /// <param name="assetNameSyntax"></param>
    /// <returns></returns>
    public JobResult CreateAndSubmitJobs(string resourceGroup, string accountName, string transformName, Asset asset, string jobName = null, ClipTime start = null, ClipTime end = null, Asset outputAsset = null, string assetNameSyntax = null)
    {
    JobResult result = new JobResult();
    string NameconvInputasset = "{Input Asset Name}";
    string NameconvTransform = "{Transform Name}";
    string NameconvShortUniqueness = "{Uniqueness}";

    Transform transform = CreateAndGetCopyCodecTransformIfNeeded(resourceGroup, accountName, transformName);
    string jobNameToUse = jobName;
    string uniqueness = Guid.NewGuid().ToString().Substring(0, 11).Replace("-", "");
    if (jobNameToUse == null)
    {
    jobNameToUse = $"job-{transform.Name}-{uniqueness}";
    }
    else if (asset != null) // job name defined but we need to add a uniqueness as there are several assets, so several jobs to submit
    {
    jobNameToUse += uniqueness;
    }


    Asset OutputAssetNow = outputAsset;
    string OutputAssetNameNow = OutputAssetNow?.Name;

    List<JobOutput> jobOutputs = new List<JobOutput>();

    if (OutputAssetNow == null)
    {
    foreach (var outputTrans in transform.Outputs)
    {

    // output asset name management
    if (assetNameSyntax != null)
    {
    OutputAssetNameNow = assetNameSyntax
    .Replace(NameconvInputasset, asset.Name)
    .Replace(NameconvTransform, transform.Name)
    .Replace(NameconvShortUniqueness, uniqueness);

    // example of syntax by default: Constants.NameconvInputasset + "-" + Constants.NameconvTransform + "-" + Constants.NameconvShortUniqueness;
    }
    else
    {
    OutputAssetNameNow = $"{asset.Name}-{transform.Name}-{uniqueness}" + ((transform.Outputs.Count > 1) ? "-" + transform.Outputs.IndexOf(outputTrans) : null);

    }
    // if several outputs, we need to add an index
    OutputAssetNameNow += ((transform.Outputs.Count > 1) ? "-" + transform.Outputs.IndexOf(outputTrans) : null);

    {
    try
    {
    OutputAssetNow = client.Assets.CreateOrUpdate(
    resourceGroup,
    accountName,
    OutputAssetNameNow,
    new Asset()
    );

    jobOutputs.Add(new JobOutputAsset(OutputAssetNameNow));

    }
    catch (Exception ex)
    {
    break;
    }
    }
    }
    }
    else
    {
    transform.Outputs.ToList().ForEach(t => jobOutputs.Add(new JobOutputAsset(OutputAssetNameNow)));
    }

    JobInputAsset jobInput = new JobInputAsset(asset.Name, start: start, end: end);
    try
    {
    Job job =
    client.Jobs.Create(
    resourceGroup,
    accountName,
    transform.Name,
    jobNameToUse,
    new Job
    {
    Input = jobInput,
    Outputs = jobOutputs,
    });

    result.JobName = jobNameToUse;
    result.OutputAssetName = OutputAssetNameNow;
    return result;


    }
    catch (Exception ex)
    {
    throw ex;
    }

    }

    /// <summary>
    /// 下载转换后的MP4资产文件
    /// </summary>
    /// <param name="resourceGroupName">资源组</param>
    /// <param name="accountName">媒体服务</param>
    /// <param name="assetName">资产名</param>
    /// <param name="resultsFolder">下载到服务器的文件路径</param>
    /// <returns></returns>
    public MemoryStream DownloadFile(string resourceGroupName, string accountName, string assetName, string resultsFolder)
    {
    AssetContainerSas assetContainerSas = client.Assets.ListContainerSas(
    resourceGroupName,
    accountName,
    assetName,
    permissions: AssetContainerPermission.Read,
    expiryTime: DateTime.UtcNow.AddHours(1).ToUniversalTime()
    );

    Uri containerSasUrl = new Uri(assetContainerSas.AssetContainerSasUrls.FirstOrDefault());
    CloudBlobContainer container = new CloudBlobContainer(containerSasUrl);

    string directory = resultsFolder;
    Directory.CreateDirectory(directory);

    var blobs = container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, 100, null, null, null).Result;

    MemoryStream ms = null;
    foreach (var blobItem in blobs.Results)
    {
    if (blobItem is CloudBlockBlob)
    {
    CloudBlockBlob blob = blobItem as CloudBlockBlob;
    if (blob.Name.ToLower().Contains(".mp4"))
    {
    string filename = Path.Combine(directory, blob.Name);
    if (blob.Name.Contains("/"))
    {
    var filepath = filename.Split('/')[0];
    if (!Directory.Exists(filepath))
    Directory.CreateDirectory(filepath);
    }
    blob.DownloadToFile(filename, FileMode.Create);

    if (File.Exists(filename))
    {
    byte[] buffer = File.ReadAllBytes(filename);
    ms = new MemoryStream(buffer, 0, buffer.Length);
    File.Delete(filename);
    }
    }

    }
    }

    return ms;
    }


    private Transform GetTransformAsync(string resourceGroup, string accountName, string transformName)
    {
    return client.Transforms.Get(resourceGroup, accountName, transformName);
    }

    调用方式:

    var _selectedAssets = liveSrv.GetAsset(resourceGroup, accountName, model.AssetName);
    var result = liveSrv.CreateAndSubmitJobs(resourceGroup, accountName, transformName, _selectedAssets);

    var path = Server.MapPath(@"Video");
    Stream stream = liveSrv.DownloadFile(resourceGroup, accountName, model.OutputAssetName, path);

    byte[] bytes = new byte[(int)stream.Length];
    stream.Read(bytes, 0, bytes.Length);
    stream.Close();
    Response.ContentType = "application/octet-stream;charset=gb2321";

    //通知浏览器下载文件而不是打开;对中文名称进行编码
    Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(model.Title + ".mp4", System.Text.Encoding.UTF8));
    Response.BinaryWrite(bytes);
    Response.Flush();
    Response.End();

  • 相关阅读:
    26_为什么我的删除刷新没有办法删除动态添加的数据呢?
    075_not in (null):这代表是什么意思呢?
    074_form表单中的value值
    025_回调函数没有遍历出数据
    073_模糊查询
    072_jsp追加与刷新数据
    071_为什么要catch return.setCode()?
    070_jstl中的三目表达式
    069_都是查询语句时得事物?
    打印周报模板
  • 原文地址:https://www.cnblogs.com/yxqah/p/13255475.html
Copyright © 2011-2022 走看看