コード例 #1
0
        private static string GetAssetId(string assetName, string jwt, string restapiuri)
        {
            string      assetId        = string.Empty;
            XmlDocument objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "Assets", null);

            foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
            {
                if (objXmlNode.ParentNode.SelectSingleNode("Name").InnerText.ToLower() == assetName.ToLower())
                {
                    assetId = objXmlNode.InnerText;
                    break;
                }
            }
            return(assetId);
        }
コード例 #2
0
        static void Main(string[] args)
        {
            //The commented code is for ACS authentication via REST API
            //string name = "willzhanmswest";
            //string name = "partnermedia1";
            //string key = System.Configuration.ConfigurationManager.AppSettings[name];
            //string mediaServicesApiServerUri = System.Configuration.ConfigurationManager.AppSettings["ApiServerUri"];
            //string acsBearerToken = Utils.GetUrlEncodedAcsBearerToken(name, key);

            XmlDocument objXmlDocument;
            string      FORMAT = "{0,-55}{1}";
            string      requestBody, path;
            string      assetId, policyId;
            //string url, requestBody, path, assetName, assetId, resourcePath;
            //string processorId, preset, jobName, outputAssetName;
            //byte[] body;

            //AAD Authentication - Client Credentials grant
            string jwt = Utils.GetUrlEncodedJWT(System.Configuration.ConfigurationManager.AppSettings["clientid"], System.Configuration.ConfigurationManager.AppSettings["clientsecret"]);
            //Console.WriteLine("JWT = {0}", jwt);
            string restapiuri = System.Configuration.ConfigurationManager.AppSettings["restapiuri"];
            //string authorizationcode = Utils.GetAuthorizationCode(System.Configuration.ConfigurationManager.AppSettings["clientid"], System.Configuration.ConfigurationManager.AppSettings["clientsecret"]);

            int id = 101; //choose an integer between 0 and 10 to test 11 AMS REST API calls with JWT token

            switch (id)
            {
            case 0:     //list MediaProcessors
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "/MediaProcessors", null);
                Console.WriteLine("{0,-55}{1,-55}{2,-55}{3,-55}", "ID", "Name", "Vendor", "Version");
                foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
                {
                    Console.WriteLine("{0,-55}{1,-55}{2,-55}{3,-55}", objXmlNode.InnerText, objXmlNode.ParentNode.SelectSingleNode("Name").InnerText, objXmlNode.ParentNode.SelectSingleNode("Vendor").InnerText, objXmlNode.ParentNode.SelectSingleNode("Version").InnerText);
                }
                break;

            case 1:     //list ILocators
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "/Locators", null);
                Console.WriteLine(FORMAT, "ID", "PATH");
                foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
                {
                    Console.WriteLine(FORMAT, objXmlNode.InnerText, objXmlNode.ParentNode.SelectSingleNode("Path").InnerText);
                }
                break;

            case 2:      //list StreamingEndpoints
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "/StreamingEndpoints", null);
                Console.WriteLine("{0,-55}{1,-55}{2,-20}{3}", "Id", "Name", "ScaleUnits", "HostName");
                foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
                {
                    Console.WriteLine("{0,-55}{1,-55}{2,-20}{3}", objXmlNode.InnerText, objXmlNode.ParentNode.SelectSingleNode("Name").InnerText, objXmlNode.ParentNode.SelectSingleNode("ScaleUnits").InnerText, objXmlNode.ParentNode.SelectSingleNode("HostName").InnerText);
                }
                break;

            case 3:     //list IAssets
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "/Assets", null);
                Console.WriteLine(FORMAT, "ID", "NAME");
                foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
                {
                    Console.WriteLine(FORMAT, objXmlNode.InnerText, objXmlNode.ParentNode.SelectSingleNode("Name").InnerText);
                }
                break;

            case 4:     //list AccessPolicy
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "/AccessPolicies", null);
                Console.WriteLine(FORMAT, "ID", "NAME");
                foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
                {
                    Console.WriteLine(FORMAT, objXmlNode.InnerText, objXmlNode.ParentNode.SelectSingleNode("Name").InnerText);
                }
                break;

            case 5:     //list IChannels
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "/Channels", null);
                Console.WriteLine(FORMAT, "ID", "NAME");
                foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
                {
                    Console.WriteLine(FORMAT, objXmlNode.InnerText, objXmlNode.ParentNode.SelectSingleNode("Name").InnerText);
                }
                break;

            case 6:     //list IPrograms
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "/Programs", null);
                Console.WriteLine(FORMAT, "ID", "NAME");
                foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
                {
                    Console.WriteLine(FORMAT, objXmlNode.InnerText, objXmlNode.ParentNode.SelectSingleNode("Name").InnerText);
                }
                break;

            case 7:     //IChannel.Reset(): the channel must be started first
                objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "/Channels('nb:chid:UUID:5c077dd2-e7f2-4814-8f53-e432c1d9f06a')/Reset", null);
                break;

            case 8:     //update program
                requestBody    = "{\"ArchiveWindowLength\":\"PT1H\"}";
                objXmlDocument = AMSClient.MakeRestCall("PATCH", jwt, restapiuri, "/Programs('nb:pgid:UUID:a3f5e002-3cb9-4d7e-acd3-349d64c4c863')", requestBody);
                break;

            case 9:     //update channel: the channel must be stopped first
                requestBody = string.Format("{{\"Output\":{{\"Hls\":{{\"FragmentsPerSegment\":{0}}}}}}}", "1");
                //requestBody = "{\"Output\":{\"Hls\":{\"FragmentsPerSegment\": 1}}}"; //the doc is incorrect
                objXmlDocument = AMSClient.MakeRestCall("PATCH", jwt, restapiuri, "/Channels('nb:chid:UUID:5c077dd2-e7f2-4814-8f53-e432c1d9f06a')", requestBody);
                break;

            //STEPS to create an asset and upload a file
            case 10:     //create an empty IAsset
                requestBody    = "{\"Name\":\"REST_test_asset\"}";
                objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "/Assets", requestBody);
                break;

            case 11:     //set AccessPolicy for writing
                requestBody    = "{\"Name\": \"RESTTestAccessPolicy\", \"DurationInMinutes\" : \"3000\", \"Permissions\" : 2 }";
                objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "AccessPolicies", requestBody);
                Console.WriteLine(objXmlDocument.OuterXml);
                break;

            case 12:     //create SAS locator: Type: 1
                assetId        = "nb:cid:UUID:5da1d9dc-b157-46d8-9d59-37139f152972";
                policyId       = "nb:pid:UUID:cde5c349-c2e6-4de9-84b2-3a6548fac1a7";
                requestBody    = string.Format("{{\"AccessPolicyId\": \"{0}\", \"AssetId\" : \"{1}\", \"StartTime\" : \"2017-10-24T16:45:53\", \"Type\" : 1 }}", policyId, assetId);
                objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "Locators", requestBody);
                Console.WriteLine(objXmlDocument.OuterXml);
                break;

            case 13:     //upload single file (Using Azure Storage REST API with SAS authentication)
                path = @"C:\Workspace\Destination\Input\SingileFile\RexonaCommercial.mp4";
                byte[] body = AzureStorageClient.GetBytesFromFile(path);
                //SAS URI of the empty container
                string sasUri = "https://partnerstorage1.blob.core.windows.net/asset-5da1d9dc-b157-46d8-9d59-37139f152972?sv=2012-02-12&sr=c&si=ad67bb92-d163-43ce-b60c-d1b150342265&sig=XHatAd16dI6apWDM%2B6SiAq0S1uo7stF5xwhMVDUSjvk%3D&st=2017-10-24T16%3A45%3A53Z&se=2017-10-26T18%3A45%3A53Z";
                //objXmlDocument = AzureStorageClient.MakeRestCall("PUT", url, body);
                objXmlDocument = AzureStorageClient.UploadBlobWithRestAPISasPermissionOnBlobContainer(sasUri, "RexonaCommercial.mp4", body);
                break;

            case 14:     //create IAsset metadata
                assetId = "nb:cid:UUID:5da1d9dc-b157-46d8-9d59-37139f152972";
                string query = string.Format("assetid='{0}'", System.Web.HttpUtility.UrlEncode(assetId));
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "CreateFileInfos", null, query: query);
                break;

            case 15:                                                                          //create a transcoding job
                string processorId     = "nb:mpid:UUID:ff4df607-d419-42f0-bc17-a481b1331e56"; //from id=0, use the latest version of Azure Media Encoder
                string preset          = "Content Adaptive Multiple Bitrate MP4";             //https://docs.microsoft.com/en-us/azure/media-services/media-services-mes-presets-overview
                string jobName         = "RETS_test_job01";
                string outputAssetName = "REST_test_output";
                assetId        = "nb:cid:UUID:5da1d9dc-b157-46d8-9d59-37139f152972";
                requestBody    = string.Format("{{\"Name\" : \"{3}\", \"InputMediaAssets\" : [{{\"__metadata\" : {{\"uri\" : \"https://media.windows.net/api/Assets('{0}')\"}}}}],  \"Tasks\" : [{{\"Configuration\" : \"{4}\", \"MediaProcessorId\" : \"{1}\",  \"TaskBody\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><taskBody><inputAsset>JobInputAsset(0)</inputAsset><outputAsset assetName=\\\"{2}\\\">JobOutputAsset(0)</outputAsset></taskBody>\"}}]}}", System.Web.HttpUtility.UrlEncode(assetId), processorId, outputAssetName, jobName, preset);
                objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "Jobs", requestBody);
                break;

            case 16:     //create read access policy for origin locator, valid for about a year
                requestBody    = "{\"Name\": \"ReadAccessPolicy\", \"DurationInMinutes\" : \"500000\", \"Permissions\" : 1 }";
                objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "AccessPolicies", requestBody);
                Console.WriteLine(objXmlDocument.OuterXml);
                break;

            case 17:     //create origin locator: Type: 2
                policyId       = "nb:pid:UUID:db236678-29de-4a33-9e9f-9d10440a1722";
                assetId        = "nb:cid:UUID:4f99a238-5da0-4e5a-b0f8-e60dc13c6406";
                requestBody    = string.Format("{{\"AccessPolicyId\": \"{0}\", \"AssetId\" : \"{1}\", \"StartTime\" : \"{2}\", \"Type\" : 2 }}", policyId, assetId, DateTime.UtcNow.AddDays(-1.0).ToString("yyyy-MM-ddTHH:mm:ss"));
                objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "Locators", requestBody);
                Console.WriteLine(objXmlDocument.OuterXml);
                break;

            case 18:     //list asset files (to get .ism file to build streaming URL)
                assetId        = "nb:cid:UUID:4f99a238-5da0-4e5a-b0f8-e60dc13c6406";
                objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, string.Format("Assets('{0}')/Files", assetId), null);
                Console.WriteLine(objXmlDocument.OuterXml);
                foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Name"))
                {
                    Console.WriteLine("{0,-55}", objXmlNode.InnerText);
                }
                break;

            //case 18: //create a Indexer job
            //    processorId = "nb:mpid:UUID:233e57fc-36bb-4f6f-8f18-3b662747a9f8";  //Indexer processor ID, from case 0
            //    preset = System.IO.File.ReadAllText(@"..\..\MAVISConfig.xml");      //Indexer job needs a configuration file
            //    preset = preset.Replace("\"", "\\\"");                              //XML contains double quotes which need to be escaped as part of JSON values
            //    jobName = "MAVIS_Job_01";
            //    outputAssetName = "MAVIS_Output_Asset_01";
            //    assetId = "nb:cid:UUID:5310435d-1500-80c3-53b9-f1e4be2cf85d";       //asset ID of uploaded MP4 (LyncSkypeSizzleVideo750k-mp4-Source)
            //    requestBody = string.Format("{{\"Name\" : \"{3}\", \"InputMediaAssets\" : [{{\"__metadata\" : {{\"uri\" : \"https://media.windows.net/api/Assets('{0}')\"}}}}],  \"Tasks\" : [{{\"Configuration\" : \"{4}\", \"MediaProcessorId\" : \"{1}\",  \"TaskBody\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><taskBody><inputAsset>JobInputAsset(0)</inputAsset><outputAsset assetName=\\\"{2}\\\">JobOutputAsset(0)</outputAsset></taskBody>\"}}]}}", System.Web.HttpUtility.UrlEncode(assetId), processorId, outputAssetName, jobName, preset);
            //    objXmlDocument = AMSClient.MakeRestCall("POST", acsBearerToken, mediaServicesApiServerUri, "Jobs", requestBody);
            //    break;
            case 101:
                path = @"C:\Workspace\Destination\Input\SingileFile\RexonaCommercial.mp4";
                string assetName = "RexonaCommercialRest";
                RunWorkflow(assetName, path, jwt, restapiuri);
                break;

            //case 21: //scale StreamingEndpoint
            //    requestBody = "{\"scaleUnits\" : 1}";  //“scaleUnit” in this case is not a property on an Entity, but rather a parameter passed to the Scale action on an StreamingEndpoint entity (The POST request below is to invoke the action). I believe the parameter name has to internally exactly match (unfortunately not case insensitive match) the parameter name in the signature of our C# method that gets called for this action. As coding convention, first letter of a parameter should be lower case, which led to this effect.
            //    resourcePath = string.Format("StreamingEndpoints('{0}')/Scale", System.Web.HttpUtility.UrlEncode("nb:oid:UUID:364e57ac-35be-0d26-05f5-6fd00b3f33fd"));
            //    objXmlDocument = AMSClient.MakeRestCall("POST", acsBearerToken, mediaServicesApiServerUri, resourcePath, requestBody);
            //    break;
            //case 10: //create a channel
            //    requestBody = "{\"Id\":null,\"Name\":\"testchannel002\",\"Description\":\"\",\"Created\":\"2017-06-01T00:00:00\",\"LastModified\":\"2017-06-14T00:00:00\",\"State\":null,\"Input\":{\"KeyFrameInterval\":null,\"StreamingProtocol\":\"FragmentedMP4\",\"AccessControl\":{\"IP\":{\"Allow\":[{\"Name\":\"testName1\",\"Address\":\"0.0.0.0\",\"SubnetPrefixLength\":0}]}},\"Endpoints\":[]},\"Preview\":{\"AccessControl\":{\"IP\":{\"Allow\":[{\"Name\":\"testName1\",\"Address\":\"0.0.0.0\",\"SubnetPrefixLength\":0}]}},\"Endpoints\":[]},\"Output\":{\"Hls\":{\"FragmentsPerSegment\":1}},\"CrossSiteAccessPolicies\":{\"ClientAccessPolicy\":null,\"CrossDomainPolicy\":null}}";
            //    objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "/Channels", requestBody);
            //    break;
            //case 30: //create Azure storage account
            //    CreateAzureStorageAccount();
            //    break;
            //case 31: //create media service account
            //    CreateMediaServiceAccount();
            //    break;
            //case 32: //GetAccountDetails
            //    ManagementRESTAPIHelper helper = new ManagementRESTAPIHelper("https://management.core.windows.net", "A3022B01D70924D819CBD0DC118D22ACAC29DE36", "2db39a66-f5c5-4b03-9d1c-71018352379b");
            //    helper.GetAccountDetails("willzhanmswest");
            //    break;
            default:
                break;
            }

            Console.WriteLine("Hit any key to finish");
            Console.ReadKey();
        }
コード例 #3
0
        private static void RunWorkflow(string assetName, string path, string jwt, string restapiuri)
        {
            //variables
            string      requestBody, assetId = string.Empty, policyId = string.Empty, policyName, locatorPath = string.Empty;
            XmlDocument objXmlDocument;

            //create empty IAsset
            requestBody    = string.Format("{{\"Name\":\"{0}\"}}", assetName);
            objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "Assets", requestBody);
            Console.WriteLine("An empty IAsset with name {0} is created.", assetName);

            //get assetId
            assetId = GetAssetId(assetName, jwt, restapiuri);
            Console.WriteLine("IAsset.Id = {0}", assetId);

            //create write access policy for SAS
            policyName     = string.Format("{0}_sas_access_policy", assetName);
            requestBody    = string.Format("{{\"Name\": \"{0}\", \"DurationInMinutes\" : \"3000\", \"Permissions\" : 2 }}", policyName);
            objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "AccessPolicies", requestBody);
            Console.WriteLine("Access policy with name {0} is created.", policyName);

            //get policyId
            policyId = GetAccessPolicyId(policyName, jwt, restapiuri);
            Console.WriteLine("For SAS URI: IAccessPolicy.Name = {0}, IAccessPolicy.Id = {1}", policyName, policyId);

            //create SAS locator
            requestBody    = string.Format("{{\"AccessPolicyId\": \"{0}\", \"AssetId\" : \"{1}\", \"StartTime\" : \"{2}\", \"Type\" : 1 }}", policyId, assetId, DateTime.UtcNow.AddDays(-1.0).ToString("yyyy-MM-ddTHH:mm:ss"));
            objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "Locators", requestBody);
            Console.WriteLine("SAS locator created with policy Id = {0} for asset Id = {1}", policyId, assetId);

            //get SAS locator path
            objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "Locators", null);
            foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
            {
                if ((objXmlNode.ParentNode.SelectSingleNode("AssetId").InnerText == assetId) && (objXmlNode.ParentNode.SelectSingleNode("Type").InnerText == "1"))   //SAS, Type=1
                {
                    locatorPath = objXmlNode.ParentNode.SelectSingleNode("Path").InnerText;
                    break;
                }
            }
            Console.WriteLine("SAS locator path = {0}", locatorPath);

            //modify SAS locator path to point to the mezzanine in Azure Storage
            string filename = System.IO.Path.GetFileName(path);

            //locatorPath = locatorPath.Replace("?", "/" + filename + "?");  //this is not needed, this is done inside AzureStorageClient.UploadBlobWithRestAPISasPermissionOnBlobContainer
            Console.WriteLine("Full SAS URI for upload mezzanine = {0}", locatorPath);

            //upload single file (Using Azure Storage REST API with SAS authentication)
            byte[] body = AzureStorageClient.GetBytesFromFile(path);
            Console.WriteLine("File upload starts ...");
            //objXmlDocument = AzureStorageClient.MakeRestCall("PUT", locatorPath, body);
            objXmlDocument = AzureStorageClient.UploadBlobWithRestAPISasPermissionOnBlobContainer(locatorPath, filename, body);
            Console.WriteLine("File upload completes");

            //create IAsset metadata
            string query = string.Format("assetid='{0}'", System.Web.HttpUtility.UrlEncode(assetId));

            objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "CreateFileInfos", null, query: query);
            Console.WriteLine("Mezzanine asset creation completes, ready to be transcoded.");

            //create and a transcoding job
            string processorId     = "nb:mpid:UUID:ff4df607-d419-42f0-bc17-a481b1331e56"; //from id=0, use the latest version of Azure Media Encoder
            string preset          = "Content Adaptive Multiple Bitrate MP4";             //https://docs.microsoft.com/en-us/azure/media-services/media-services-mes-presets-overview
            string jobName         = string.Format("{0}_encode_job", assetName);
            string outputAssetName = string.Format("Output_Asset_{0}", assetName);

            requestBody    = string.Format("{{\"Name\" : \"{3}\", \"InputMediaAssets\" : [{{\"__metadata\" : {{\"uri\" : \"https://media.windows.net/api/Assets('{0}')\"}}}}],  \"Tasks\" : [{{\"Configuration\" : \"{4}\", \"MediaProcessorId\" : \"{1}\",  \"TaskBody\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><taskBody><inputAsset>JobInputAsset(0)</inputAsset><outputAsset assetName=\\\"{2}\\\">JobOutputAsset(0)</outputAsset></taskBody>\"}}]}}", System.Web.HttpUtility.UrlEncode(assetId), processorId, outputAssetName, jobName, preset);
            objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "Jobs", requestBody);
            Console.WriteLine("AMS encoder job submitted with preset: \"{0}\"", preset);

            //create read access policy for origin locator, valid for about a year
            policyName     = string.Format("{0}_origin_access_policy", assetName);
            requestBody    = string.Format("{{\"Name\": \"{0}\", \"DurationInMinutes\" : \"500000\", \"Permissions\" : 1 }}", policyName);
            objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "AccessPolicies", requestBody);

            //retrieve the read access policy ID
            policyId = GetAccessPolicyId(policyName, jwt, restapiuri);
            Console.WriteLine("For origin URI: IAccessPolicy.Name = {0}, IAccessPolicy.Id = {1}", policyName, policyId);

            //get job output asset ID to be published
            assetId = GetAssetId(outputAssetName, jwt, restapiuri);

            //create origin locator: Type: 2
            requestBody    = string.Format("{{\"AccessPolicyId\": \"{0}\", \"AssetId\" : \"{1}\", \"StartTime\" : \"{2}\", \"Type\" : 2 }}", policyId, assetId, DateTime.UtcNow.AddDays(-1.0).ToString("yyyy-MM-ddTHH:mm:ss"));
            objXmlDocument = AMSClient.MakeRestCall("POST", jwt, restapiuri, "Locators", requestBody);
            Console.WriteLine("Asset {0} has been published", assetId);

            //get origin locator path
            objXmlDocument = AMSClient.MakeRestCall("GET", jwt, restapiuri, "Locators", null);
            foreach (XmlNode objXmlNode in objXmlDocument.GetElementsByTagName("Id"))
            {
                if ((objXmlNode.ParentNode.SelectSingleNode("AssetId").InnerText == assetId) && (objXmlNode.ParentNode.SelectSingleNode("Type").InnerText == "2"))   //origin, Type=2
                {
                    locatorPath = objXmlNode.ParentNode.SelectSingleNode("Path").InnerText;
                    break;
                }
            }
            Console.WriteLine("Origin locator path = {0}", locatorPath);
            Console.WriteLine("Origin URL: {0}{1}.ism/manifest", locatorPath, System.IO.Path.GetFileNameWithoutExtension(path));
            Console.WriteLine("Playback URL: {0}?url={1}{2}.ism/manifest", "http://aka.ms/amtest", locatorPath, System.IO.Path.GetFileNameWithoutExtension(path));
        }