无法在Azure媒体服务资产中存储文件大小数据

问题描述 投票:0回答:1

目前正在为现有的基于Web的媒体服务构建web api以对上传的视频进行编码。

我的解决方案的目标是创建一个api调用,我将发送mp4链接并进行处理(给定mp4链接的编码和流)。我能够获取mp4并下载到服务器并重新上载到自己的blob存储。但是,如果我检查AMS资源管理器,我传递的每个参数都存在,但文件大小除外。这是我创建的WEB API调用(现有媒体服务表单方法的完全复制.(https://tiltestingstreaming.azurewebsites.net/ )

    [HttpPost]
    public JsonResult UploadApi(String video_url)
    {
        var id = 1;
        WebClient client = new WebClient();
        var videoStream = new MemoryStream(client.DownloadData(video_url));

        var container = CloudStorageAccount.Parse(mediaServiceStorageConnectionString).CreateCloudBlobClient().GetContainerReference(mediaServiceStorageContainerReference);

        container.CreateIfNotExists();
        var fileName = Path.GetFileName(video_url);

        var fileToUpload = new CloudFile()
        {
            BlockCount = 1,
            FileName = fileName,
            Size = videoStream.Length,
            BlockBlob = container.GetBlockBlobReference(fileName),
            StartTime = DateTime.Now,
            IsUploadCompleted = false,
            UploadStatusMessage = string.Empty
        };

        Session.Add("CurrentFile", fileToUpload);

        byte[] chunk = new byte[videoStream.Length];
        //request.InputStream.Read(chunk, 0, Convert.ToInt32(request.Length));
        //JsonResult returnData = null;
        string fileSession = "CurrentFile";
        CloudFile model = (CloudFile)Session[fileSession];    
        var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(
                string.Format(CultureInfo.InvariantCulture, "{0:D4}", id)));
        try
        {
            model.BlockBlob.PutBlock(
                blockId,
                videoStream, null, null,
                new BlobRequestOptions()
                {
                    RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(10), 3)
                },
                null);
        }
        catch (StorageException e)
        {
            model.IsUploadCompleted = true;
            model.UploadStatusMessage = "Failed to Upload file. Exception - " + e.Message;
            return Json(new { error = true, isLastBlock = false, message = model.UploadStatusMessage });
        }

        var blockList = Enumerable.Range(1, (int)model.BlockCount).ToList<int>().ConvertAll(rangeElement => Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0:D4}", rangeElement))));
        model.BlockBlob.PutBlockList(blockList);
        var duration = DateTime.Now - model.StartTime;
        float fileSizeInKb = model.Size / 1024;
        string fileSizeMessage = fileSizeInKb > 1024 ? string.Concat((fileSizeInKb / 1024).ToString(CultureInfo.CurrentCulture), " MB") : string.Concat(fileSizeInKb.ToString(CultureInfo.CurrentCulture), " KB");
        model.UploadStatusMessage = string.Format(CultureInfo.CurrentCulture, "File of size {0} took {1} seconds to upload.", fileSizeMessage, duration.TotalSeconds);

        IAsset mediaServiceAsset = CreateMediaAsset(model);
        model.AssetId = mediaServiceAsset.Id;

        //if (id == model.BlockCount){CommitAllChunks(model);}
        return Json(new { error = false, isLastBlock = false, message = string.Empty, filename = fileName,filesize = videoStream.Length });
    }

表单方法解决方案中使用的函数。

[HttpPost]
    public ActionResult SetMetadata(int blocksCount, string fileName, long fileSize)
    {
        var container = CloudStorageAccount.Parse(mediaServiceStorageConnectionString).CreateCloudBlobClient().GetContainerReference(mediaServiceStorageContainerReference);

        container.CreateIfNotExists();

        var fileToUpload = new CloudFile()
        {
            BlockCount = blocksCount,
            FileName = fileName,
            Size = fileSize,
            BlockBlob = container.GetBlockBlobReference(fileName),
            StartTime = DateTime.Now,
            IsUploadCompleted = false,
            UploadStatusMessage = string.Empty
        };

        Session.Add("CurrentFile", fileToUpload);

        return Json(true);
    }

    [HttpPost]
    [ValidateInput(false)]
    public ActionResult UploadChunk(int id)
    {
        HttpPostedFileBase request = Request.Files["Slice"];
        byte[] chunk = new byte[request.ContentLength];
        request.InputStream.Read(chunk, 0, Convert.ToInt32(request.ContentLength));
        JsonResult returnData = null;
        string fileSession = "CurrentFile";
        if (Session[fileSession] != null)
        {
            CloudFile model = (CloudFile)Session[fileSession];
            returnData = UploadCurrentChunk(model, chunk, id);
            if (returnData != null)
            {
                return returnData;
            }
            if (id == model.BlockCount)
            {
                return CommitAllChunks(model);
            }
        }
        else
        {
            returnData = Json(new
            {
                error = true,
                isLastBlock = false,
                message = string.Format(CultureInfo.CurrentCulture, "Failed to Upload file.", "Session Timed out")
            });
            return returnData;
        }
        return Json(new { error = false, isLastBlock = false, message = string.Empty });
    }

    private JsonResult UploadCurrentChunk(CloudFile model, byte[] chunk, int id)
    {
        using (var chunkStream = new MemoryStream(chunk))
        {
            var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(
                    string.Format(CultureInfo.InvariantCulture, "{0:D4}", id)));
            try
            {
                model.BlockBlob.PutBlock(
                    blockId,
                    chunkStream, null, null,
                    new BlobRequestOptions()
                    {
                        RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(10), 3)
                    },
                    null);
                return null;
            }
            catch (StorageException e)
            {
                model.IsUploadCompleted = true;
                model.UploadStatusMessage = "Failed to Upload file. Exception - " + e.Message;
                return Json(new { error = true, isLastBlock = false, message = model.UploadStatusMessage });
            }
        }
    }

    private ActionResult CommitAllChunks(CloudFile model)
    {
        model.IsUploadCompleted = true;
        bool errorInOperation = false;
        try
        {
            var blockList = Enumerable.Range(1, (int)model.BlockCount).ToList<int>().ConvertAll(rangeElement => Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0:D4}", rangeElement))));
            model.BlockBlob.PutBlockList(blockList);
            var duration = DateTime.Now - model.StartTime;
            float fileSizeInKb = model.Size / 1024;
            string fileSizeMessage = fileSizeInKb > 1024 ? string.Concat((fileSizeInKb / 1024).ToString(CultureInfo.CurrentCulture), " MB") : string.Concat(fileSizeInKb.ToString(CultureInfo.CurrentCulture), " KB");
            model.UploadStatusMessage = string.Format(CultureInfo.CurrentCulture, "File of size {0} took {1} seconds to upload.", fileSizeMessage, duration.TotalSeconds);

            IAsset mediaServiceAsset = CreateMediaAsset(model);
            model.AssetId = mediaServiceAsset.Id;
        }
        catch (StorageException e)
        {
            model.UploadStatusMessage = "Failed to upload file. Exception - " + e.Message;
            errorInOperation = true;
        }
        return Json(new
        {
            error = errorInOperation,
            isLastBlock = model.IsUploadCompleted,
            message = model.UploadStatusMessage,
            assetId = model.AssetId
        });
    }

    private IAsset CreateMediaAsset(CloudFile model)
    {
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(mediaServiceStorageConnectionString);
        CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer mediaBlobContainer = cloudBlobClient.GetContainerReference(mediaServiceStorageContainerReference);

        mediaBlobContainer.CreateIfNotExists();

        // Create a new asset.
        IAsset asset = context.Assets.Create("UploadedVideo-" + Guid.NewGuid().ToString().ToLower(), AssetCreationOptions.None);
        IAccessPolicy writePolicy = context.AccessPolicies.Create("writePolicy", TimeSpan.FromMinutes(120), AccessPermissions.Write);
        ILocator destinationLocator = context.Locators.CreateLocator(LocatorType.Sas, asset, writePolicy);

        // Get the asset container URI and copy blobs from mediaContainer to assetContainer.
        Uri uploadUri = new Uri(destinationLocator.Path);
        string assetContainerName = uploadUri.Segments[1];
        CloudBlobContainer assetContainer = cloudBlobClient.GetContainerReference(assetContainerName);
        string fileName = HttpUtility.UrlDecode(Path.GetFileName(model.BlockBlob.Uri.AbsoluteUri));

        var sourceCloudBlob = mediaBlobContainer.GetBlockBlobReference(fileName);
        sourceCloudBlob.FetchAttributes();

        if (sourceCloudBlob.Properties.Length > 0)
        {
            IAssetFile assetFile = asset.AssetFiles.Create(fileName);
            var destinationBlob = assetContainer.GetBlockBlobReference(fileName);

            destinationBlob.DeleteIfExists();
            destinationBlob.StartCopy(sourceCloudBlob);
            destinationBlob.FetchAttributes();
            if (sourceCloudBlob.Properties.Length != destinationBlob.Properties.Length)
                model.UploadStatusMessage += "Failed to copy as Media Asset!";
        }
        destinationLocator.Delete();
        writePolicy.Delete();
        sourceCloudBlob.Delete();  //delete temp blob

        // Refresh the asset.
        asset = context.Assets.Where(a => a.Id == asset.Id).FirstOrDefault();

        var ismAssetFiles = asset.AssetFiles.FirstOrDefault();
        ismAssetFiles.IsPrimary = true;
        ismAssetFiles.Update();

        model.UploadStatusMessage += " Media file uploaded successfully by id: " + asset.Id;
        model.AssetId = asset.Id;

        return asset;
    }

    [HttpPost]
    public ActionResult EncodeToAdaptiveBitrateMP4s(string assetId)
    {
        // Note: You need atleast 1 reserve streaming unit for dynamic packaging of encoded media. If you don't have that, you can't see video file playing.

        IAsset inputAsset = GetAssetById(assetId);
        string token = string.Empty;
        string uploadFileOriginalName = string.Empty;

        ////// Without preset (say default preset), works very well
        //IJob job = context.Jobs.CreateWithSingleTask(MediaProcessorNames.AzureMediaEncoder,
        //    MediaEncoderTaskPresetStrings.H264AdaptiveBitrateMP4Set720p,
        //    inputAsset,
        //    "UploadedVideo-" + Guid.NewGuid().ToString().ToLower() + "-Adaptive-Bitrate-MP4",
        //    AssetCreationOptions.None);
        //job.Submit();
        //IAsset encodedOutputAsset = job.OutputMediaAssets[0];


        //// XML Preset
        IJob job = context.Jobs.Create(inputAsset.Name);
        IMediaProcessor processor = GetLatestMediaProcessorByName("Media Encoder Standard");
        string configuration = System.IO.File.ReadAllText(HttpContext.Server.MapPath("~/MediaServicesCustomPreset.xml"));
        ITask task = job.Tasks.AddNew(inputAsset.Name + "- encoding task", processor, configuration, TaskOptions.None);
        task.InputAssets.Add(inputAsset);
        task.OutputAssets.AddNew(inputAsset.Name + "-Adaptive-Bitrate-MP4", AssetCreationOptions.None);
        job.Submit();
        IAsset encodedAsset = job.OutputMediaAssets[0];

        // process policy & encryption
        ProcessPolicyAndEncryption(encodedAsset);

        // Get file name
        string fileSession = "CurrentFile";
        if (Session[fileSession] != null)
        {
            CloudFile model = (CloudFile)Session[fileSession];
            uploadFileOriginalName = model.FileName;
        }

        // Generate Streaming URL
        string smoothStreamingUri = GetStreamingOriginLocator(encodedAsset, uploadFileOriginalName);

        // add jobid and output asset id in database
        AzureMediaServicesContext db = new AzureMediaServicesContext();
        var video = new Video();
        video.RowAssetId = assetId;
        video.EncodingJobId = job.Id;
        video.EncodedAssetId = encodedAsset.Id;
        video.LocatorUri = smoothStreamingUri;
        video.IsEncrypted = useAESRestriction;
        db.Videos.Add(video);
        db.SaveChanges();

        if (useAESRestriction)
        {
            token = AzureMediaAsset.GetTestToken(encodedAsset.Id, encodedAsset);
        }

        // Remove session
        Session.Remove("CurrentFile");

        // return success response
        return Json(new
        {
            error = false,
            message = "Congratulations! Video is uploaded and pipelined for encoding, check console log for after encoding playback details.",
            assetId = assetId,
            jobId = job.Id,
            locator = smoothStreamingUri,
            encrypted = useAESRestriction,
            token = token
        });

    }

我遇到的实际挑战是,我不确定为什么下载的远程mp4文件的文件大小不存储在媒体服务资产文件中,但我能够通过my api调用的json响应返回值。请查看API响应的附加屏幕截图。 enter image description hereenter image description here

c# azure-media-services
1个回答
0
投票

能够找出我自己的问题。我需要做的就是复制绑定到ActionResult数据类型的编码函数的函数。我认为ActionResult是表单方法解决方案的一部分,我正在构建一个工作表单方法的WebAPI调用解决方案。

从原来的通话功能

[HttpPost] public ActionResult EncodeToAdaptiveBitrateMP4s(string assetId)

我将整个函数复制到我的Web Api Call函数中,如下所示:

[HttpPost]
    public JsonResult UploadApi(String video_url)
    {
        var id = 1;
        WebClient client = new WebClient();
        var videoStream = new MemoryStream(client.DownloadData(video_url));

        var container = CloudStorageAccount.Parse(mediaServiceStorageConnectionString).CreateCloudBlobClient().GetContainerReference(mediaServiceStorageContainerReference);

        container.CreateIfNotExists();
        var fileName = Path.GetFileName(video_url);

        var fileToUpload = new CloudFile()
        {
            BlockCount = 1,
            FileName = fileName,
            Size = videoStream.Length,
            BlockBlob = container.GetBlockBlobReference(fileName),
            StartTime = DateTime.Now,
            IsUploadCompleted = false,
            UploadStatusMessage = string.Empty
        };

        Session.Add("CurrentFile", fileToUpload);

        byte[] chunk = new byte[videoStream.Length];
        //request.InputStream.Read(chunk, 0, Convert.ToInt32(request.Length));
        //JsonResult returnData = null;
        string fileSession = "CurrentFile";
        CloudFile model = (CloudFile)Session[fileSession];    
        var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(
                string.Format(CultureInfo.InvariantCulture, "{0:D4}", id)));
        try
        {
            model.BlockBlob.PutBlock(
                blockId,
                videoStream, null, null,
                new BlobRequestOptions()
                {
                    RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(10), 3)
                },
                null);
        }
        catch (StorageException e)
        {
            model.IsUploadCompleted = true;
            model.UploadStatusMessage = "Failed to Upload file. Exception - " + e.Message;
            return Json(new { error = true, isLastBlock = false, message = model.UploadStatusMessage });
        }

        var blockList = Enumerable.Range(1, (int)model.BlockCount).ToList<int>().ConvertAll(rangeElement => Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0:D4}", rangeElement))));
        model.BlockBlob.PutBlockList(blockList);
        var duration = DateTime.Now - model.StartTime;
        float fileSizeInKb = model.Size / 1024;
        string fileSizeMessage = fileSizeInKb > 1024 ? string.Concat((fileSizeInKb / 1024).ToString(CultureInfo.CurrentCulture), " MB") : string.Concat(fileSizeInKb.ToString(CultureInfo.CurrentCulture), " KB");
        model.UploadStatusMessage = string.Format(CultureInfo.CurrentCulture, "File of size {0} took {1} seconds to upload.", fileSizeMessage, duration.TotalSeconds);

        IAsset mediaServiceAsset = CreateMediaAsset(model);
        model.AssetId = mediaServiceAsset.Id;

        // Note: You need atleast 1 reserve streaming unit for dynamic packaging of encoded media. If you don't have that, you can't see video file playing.
        var assetId = model.AssetId;
        IAsset inputAsset = GetAssetById(assetId);
        string token = string.Empty;
        string uploadFileOriginalName = string.Empty;

        ////// Without preset (say default preset), works very well
        //IJob job = context.Jobs.CreateWithSingleTask(MediaProcessorNames.AzureMediaEncoder,
        //    MediaEncoderTaskPresetStrings.H264AdaptiveBitrateMP4Set720p,
        //    inputAsset,
        //    "UploadedVideo-" + Guid.NewGuid().ToString().ToLower() + "-Adaptive-Bitrate-MP4",
        //    AssetCreationOptions.None);
        //job.Submit();
        //IAsset encodedOutputAsset = job.OutputMediaAssets[0];


        //// XML Preset
        IJob job = context.Jobs.Create(inputAsset.Name);
        IMediaProcessor processor = GetLatestMediaProcessorByName("Media Encoder Standard");
        string configuration = System.IO.File.ReadAllText(HttpContext.Server.MapPath("~/MediaServicesCustomPreset.xml"));
        ITask task = job.Tasks.AddNew(inputAsset.Name + "- encoding task", processor, configuration, TaskOptions.None);
        task.InputAssets.Add(inputAsset);
        task.OutputAssets.AddNew(inputAsset.Name + "-Adaptive-Bitrate-MP4", AssetCreationOptions.None);
        job.Submit();
        IAsset encodedAsset = job.OutputMediaAssets[0];

        // process policy & encryption
        ProcessPolicyAndEncryption(encodedAsset);

        // Get file name
        uploadFileOriginalName = model.FileName;

        // Generate Streaming URL
        string smoothStreamingUri = GetStreamingOriginLocator(encodedAsset, uploadFileOriginalName);

        // add jobid and output asset id in database
        AzureMediaServicesContext db = new AzureMediaServicesContext();
        var video = new Video();
        video.RowAssetId = assetId;
        video.EncodingJobId = job.Id;
        video.EncodedAssetId = encodedAsset.Id;
        video.LocatorUri = smoothStreamingUri;
        video.IsEncrypted = useAESRestriction;
        db.Videos.Add(video);
        db.SaveChanges();

        if (useAESRestriction)
        {
            token = AzureMediaAsset.GetTestToken(encodedAsset.Id, encodedAsset);
        }

        // Remove session
        Session.Remove("CurrentFile");

        // return success response
        return Json(new
        {
            error = false,
            message = "Congratulations! Video is uploaded and pipelined for encoding, check console log for after encoding playback details.",
            assetId = assetId,
            jobId = job.Id,
            locator = smoothStreamingUri,
            encrypted = useAESRestriction,
            token = token
        });

        //if (id == model.BlockCount){CommitAllChunks(model);}
        //return Json(new { error = false, isLastBlock = false, message = string.Empty, filename = fileName,filesize = videoStream.Length });
    }

然而,这种解决方案是僵化的,而不是长期解决方案,但概念是存在的,能够实现我的目标。我将重做我的代码并重新创建一个更灵活的解决方案。

注意:我不是C#开发人员。尊重像我这样的初学者。

© www.soinside.com 2019 - 2024. All rights reserved.