مسارات صوتية وصفية للإشارة
هل تبحث عن وثائق خدمات الوسائط v2 ؟
هل تواجه مشكلة؟ راجع دليل استكشاف الأخطاء وإصلاحها للحصول على حلول للمشكلات المتعلقة باستخدام خدمات الوسائط.
يمكن العثور على نماذج التعليمات البرمجية في صفحة العينات .
يمكنك إضافة مسار سرد إلى الفيديو لمساعدة العملاء ضعاف البصر على متابعة تسجيل الفيديو من خلال الاستماع إلى السرد. في Media Services v3، يمكنك الإشارة إلى مسارات صوتية وصفية عن طريق إضافة تعليقات توضيحية إلى مسار الصوت في ملف البيان.
توضح هذه المقالة كيفية ترميز فيديو، وتحميل ملف MP4 للصوت فقط (برنامج ترميز AAC) يحتوي على صوت وصفي في أصل الإخراج، وتحرير ملف .ism لتضمين الصوت الوصفي.
المتطلبات الأساسية
- أنشئ حساباً لـMedia Services .
- اتبع الخطوات الواردة في الوصول إلى واجهة برمجة تطبيقات خدمات وسائط Azure باستخدام Azure CLI واحفظ بيانات الاعتماد. لأنك ستحتاج إلى استخدامها للوصول إلى واجهة برمجة التطبيقات.
- مراجعة التعبئة والتغليف الديناميكي.
- راجع البرنامج التعليمي Upload مقاطع الفيديو وترميزها ودفقها.
قم بإنشاء أصل إدخال وتحميل ملف محلي فيه
تقوم الدالة CreateInputAsset بإنشاء أصل إدخال جديد وتحميل ملف الفيديو المحلي المحدد فيه. يتم استخدام هذا الأصل كمدخل لمهمة الترميز الخاصة بك. في الإصدار 3 من خدمات الوسائط، يمكن أن يكون الإدخال إلى الوظيفة أحد الأصول، أو يمكن أن يكون محتوى توفره لحساب خدمات الوسائط عبر عناوين URL ل HTTPS.
في Media Services v3، يمكنك استخدام Azure Storage APIs لتحميل الملفات. يوضح مقتطف .NET التالي كيف.
تنفذ الدالة التالية هذه الإجراءات:
- إنشاء أصل
- الحصول على عنوان URL SAS قابل للكتابة إلى حاوية الأصل في التخزين
- تحميل الملف إلى الحاوية في التخزين باستخدام عنوان URL SAS
private static async Task<Asset> CreateInputAssetAsync(
IAzureMediaServicesClient client,
string resourceGroupName,
string accountName,
string assetName,
string fileToUpload)
{
// In this example, we are assuming that the asset name is unique.
//
// If you already have an asset with the desired name, use the Assets.Get method
// to get the existing asset. In Media Services v3, the Get method on entities returns null
// if the entity doesn't exist (a case-insensitive check on the name).
// Call Media Services API to create an Asset.
// This method creates a container in storage for the Asset.
// The files (blobs) associated with the asset will be stored in this container.
Asset asset = await client.Assets.CreateOrUpdateAsync(resourceGroupName, accountName, assetName, new Asset());
// Use Media Services API to get back a response that contains
// SAS URL for the Asset container into which to upload blobs.
// That is where you would specify read-write permissions
// and the exparation time for the SAS URL.
var response = await client.Assets.ListContainerSasAsync(
resourceGroupName,
accountName,
assetName,
permissions: AssetContainerPermission.ReadWrite,
expiryTime: DateTime.UtcNow.AddHours(4).ToUniversalTime());
var sasUri = new Uri(response.AssetContainerSasUrls.First());
// Use Storage API to get a reference to the Asset container
// that was created by calling Asset's CreateOrUpdate method.
BlobContainerClient container = new BlobContainerClient(sasUri);
BlobClient blob = container.GetBlobClient(Path.GetFileName(fileToUpload));
// Use Strorage API to upload the file into the container in storage.
await blob.UploadAsync(fileToUpload);
return asset;
}
إذا كنت بحاجة إلى تمرير اسم أصل الإدخال الذي تم إنشاؤه إلى أساليب أخرى، فتأكد من استخدام الخاصية Name على كائن الأصل الذي تم إرجاعه من CreateInputAssetAsync، على سبيل المثال، inputAsset.Name.
إنشاء أصل إخراج لتخزين نتيجة مهمة الترميز
يخزن الناتج "Asset" نتيجة مهمة ترميز. توضح الدالة التالية كيفية إنشاء أصل إخراج.
private static async Task<Asset> CreateOutputAssetAsync(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string assetName)
{
bool existingAsset = true;
Asset outputAsset;
try
{
// Check if an Asset already exists
outputAsset = await client.Assets.GetAsync(resourceGroupName, accountName, assetName);
}
catch (ErrorResponseException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
existingAsset = false;
}
Asset asset = new Asset();
string outputAssetName = assetName;
if (existingAsset)
{
// Name collision! In order to get the sample to work, let's just go ahead and create a unique asset name
// Note that the returned Asset can have a different name than the one specified as an input parameter.
// You may want to update this part to throw an Exception instead, and handle name collisions differently.
string uniqueness = $"-{Guid.NewGuid():N}";
outputAssetName += uniqueness;
Console.WriteLine("Warning – found an existing Asset with name = " + assetName);
Console.WriteLine("Creating an Asset with this name instead: " + outputAssetName);
}
return await client.Assets.CreateOrUpdateAsync(resourceGroupName, accountName, outputAssetName, asset);
}
إذا كنت بحاجة إلى تمرير اسم أصل الإخراج الذي تم إنشاؤه إلى أساليب أخرى، فتأكد من استخدام الخاصية Name على كائن الأصل الذي تم إرجاعه من CreateIOutputAssetAsync، على سبيل المثال، outputAsset.Name.
في حالة هذه المقالة، قم بتمرير outputAsset.Name القيمة إلى SubmitJobAsync الدالتين و UploadAudioIntoOutputAsset .
إنشاء تحويل ووظيفة ترميز الملف الذي تم تحميله
عند ترميز المحتوى أو معالجته في خدمات الوسائط، فمن المعتاد إعداد إعدادات الترميز باعتبارها وصفة. يمكنك بعد ذلك إرسال وظيفة لتطبيق تلك الوصفة على مقطع فيديو. من خلال تقديم وظائف جديدة لكل فيديو جديد، فأنت تطبق هذه الوصفة على جميع مقاطع الفيديو في مكتبتك. تسمى الوصفة في خدمات الوسائط باسم "التحويل". لمزيد من المعلومات، راجع "التحويلات والوظائف". العينة الموصوفة في هذا البرنامج التعليمي تحدد الوصفة التي تُرمز الفيديو من أجل بثه إلى مجموعة متنوعة من أجهزة iOS وAndroid.
ينشئ المثال التالي تحويلا (إذا لم يكن موجودا).
private static async Task<Transform> GetOrCreateTransformAsync(
IAzureMediaServicesClient client,
string resourceGroupName,
string accountName,
string transformName)
{
bool createTransform = false;
Transform transform = null;
try
{
// Does a transform already exist with the desired name? Assume that an existing Transform with the desired name
// also uses the same recipe or Preset for processing content.
transform = client.Transforms.Get(resourceGroupName, accountName, transformName);
}
catch (ErrorResponseException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
createTransform = true;
}
if (createTransform)
{
// You need to specify what you want it to produce as an output
TransformOutput[] output = new TransformOutput[]
{
new TransformOutput
{
// The preset for the Transform is set to one of Media Services built-in sample presets.
// You can customize the encoding settings by changing this to use "StandardEncoderPreset" class.
Preset = new BuiltInStandardEncoderPreset()
{
// This sample uses the built-in encoding preset for Adaptive Bitrate Streaming.
PresetName = EncoderNamedPreset.AdaptiveStreaming
}
}
};
// Create the Transform with the output defined above
transform = await client.Transforms.CreateOrUpdateAsync(resourceGroupName, accountName, transformName, output);
}
return transform;
}
ترسل الدالة التالية وظيفة.
private static async Task<Job> SubmitJobAsync(IAzureMediaServicesClient client,
string resourceGroupName,
string accountName,
string transformName,
string jobName,
string inputAssetName,
string outputAssetName)
{
// Use the name of the created input asset to create the job input.
JobInput jobInput = new JobInputAsset(assetName: inputAssetName);
JobOutput[] jobOutputs =
{
new JobOutputAsset(outputAssetName),
};
// In this example, we are assuming that the job name is unique.
//
// If you already have a job with the desired name, use the Jobs.Get method
// to get the existing job. In Media Services v3, the Get method on entities returns null
// if the entity doesn't exist (a case-insensitive check on the name).
Job job = await client.Jobs.CreateAsync(
resourceGroupName,
accountName,
transformName,
jobName,
new Job
{
Input = jobInput,
Outputs = jobOutputs,
});
return job;
}
انتظر حتى تكتمل المهمة
المهمة تستغرق بعض الوقت حتى الاكتمال؛ وعند إتمامها، تُريد أن تعلم بذلك. نوصي باستخدام Event Grid لانتظار اكتمال المهمة.
تمر الوظيفة عادة بالحالات التالية: مجدولة، في قائمة الانتظار، معالجة، منتهية (الحالة النهائية). إذا حدث أي خطأ بالعملية، تكون الحالة الظاهرة أمامك "خطأ" . إذا كانت المهمة قيد الإلغاء، فستخطر بعبارة "جاري الإلغاء" ثم "انتهى الإلغاء" عند الانتهاء.
لمزيد من المعلومات، راجع معالجة أحداث Event Grid.
Upload ملف MP4 للصوت فقط
Upload ملف MP4 الإضافي للصوت فقط (برنامج ترميز AAC) الذي يحتوي على صوت وصفي في أصل الإخراج.
private static async Task UpoadAudioIntoOutputAsset(
IAzureMediaServicesClient client,
string resourceGroupName,
string accountName,
string outputAssetName,
string fileToUpload)
{
// Use the Assets.Get method to get the existing asset.
// In Media Services v3, the Get method on entities returns null
// if the entity doesn't exist (a case-insensitive check on the name).
// Call Media Services API to create an Asset.
// This method creates a container in storage for the Asset.
// The files (blobs) associated with the asset will be stored in this container.
Asset asset = await client.Assets.GetAsync(resourceGroupName, accountName, outputAssetName);
if (asset != null)
{
// Use Media Services API to get back a response that contains
// SAS URL for the Asset container into which to upload blobs.
// That is where you would specify read-write permissions
// and the exparation time for the SAS URL.
var response = await client.Assets.ListContainerSasAsync(
resourceGroupName,
accountName,
outputAssetName,
permissions: AssetContainerPermission.ReadWrite,
expiryTime: DateTime.UtcNow.AddHours(4).ToUniversalTime());
var sasUri = new Uri(response.AssetContainerSasUrls.First());
// Use Storage API to get a reference to the Asset container
// that was created by calling Asset's CreateOrUpdate method.
CloudBlobContainer container = new CloudBlobContainer(sasUri);
var blob = container.GetBlockBlobReference(Path.GetFileName(fileToUpload));
// Use Strorage API to upload the file into the container in storage.
await blob.UploadFromFileAsync(fileToUpload);
}
}
فيما يلي مثال على استدعاء للدالة UpoadAudioIntoOutputAsset :
await UpoadAudioIntoOutputAsset(client, config.ResourceGroup, config.AccountName, outputAsset.Name, "audio_description.m4a");
تحرير ملف .ism
عند الانتهاء من مهمة الترميز الخاصة بك، سيحتوي أصل الإخراج على الملفات التي تم إنشاؤها بواسطة مهمة الترميز.
في مدخل Microsoft Azure، انتقل إلى حساب التخزين المقترن بحساب خدمات الوسائط.
ابحث عن الحاوية باسم أصل الإخراج الخاص بك.
في الحاوية، ابحث عن ملف .ism وانقر فوق Edit blob (في النافذة اليمنى).
قم بتحرير ملف .ism عن طريق إضافة معلومات حول ملف MP4 للصوت فقط الذي تم تحميله (برنامج ترميز AAC) الذي يحتوي على صوت وصفي واضغط على حفظ عند الانتهاء.
للإشارة إلى مسارات الصوت الوصفية، تحتاج إلى إضافة معلمات "إمكانية وصول ذوي الاحتياجات الخاصة" و"الدور" إلى ملف .ism. تقع على عاتقك مسؤولية تعيين هذه المعلمات بشكل صحيح للإشارة إلى مسار صوتي كوصف صوتي. على سبيل المثال، أضف
<param name="accessibility" value="description" />و<param name="role" value="alternate" />إلى ملف .ism لمسار صوت معين، كما هو موضح في المثال التالي.
<?xml version="1.0" encoding="utf-8"?>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
<head>
<meta name="clientManifestRelativePath" content="ignite.ismc" />
<meta name="formats" content="mp4-v3" />
</head>
<body>
<switch>
<audio src="ignite_320x180_AACAudio_381.mp4" systemBitrate="128041" systemLanguage="eng">
<param name="systemBitrate" value="128041" valuetype="data" />
<param name="trackID" value="2" valuetype="data" />
<param name="trackName" value="aac_eng_2_128041_2_1" valuetype="data" />
<param name="systemLanguage" value="eng" valuetype="data" />
<param name="trackIndex" value="ignite_320x180_AACAudio_381_2.mpi" valuetype="data" />
</audio>
<audio src="audio_description.m4a" systemBitrate="194000" systemLanguage="eng">
<param name="trackName" value="aac_eng_audio_description" />
<param name="accessibility" value="description" />
<param name="role" value="alternate" />
</audio>
<video src="ignite_1280x720_AACAudio_3549.mp4" systemBitrate="3549855">
<param name="systemBitrate" value="3549855" valuetype="data" />
<param name="trackID" value="1" valuetype="data" />
<param name="trackName" value="video" valuetype="data" />
<param name="trackIndex" value="ignite_1280x720_AACAudio_3549_1.mpi" valuetype="data" />
</video>
<video src="ignite_960x540_AACAudio_2216.mp4" systemBitrate="2216764">
<param name="systemBitrate" value="2216764" valuetype="data" />
<param name="trackID" value="1" valuetype="data" />
<param name="trackName" value="video" valuetype="data" />
<param name="trackIndex" value="ignite_960x540_AACAudio_2216_1.mpi" valuetype="data" />
</video>
<video src="ignite_640x360_AACAudio_1154.mp4" systemBitrate="1154569">
<param name="systemBitrate" value="1154569" valuetype="data" />
<param name="trackID" value="1" valuetype="data" />
<param name="trackName" value="video" valuetype="data" />
<param name="trackIndex" value="ignite_640x360_AACAudio_1154_1.mpi" valuetype="data" />
</video>
<video src="ignite_480x270_AACAudio_721.mp4" systemBitrate="721893">
<param name="systemBitrate" value="721893" valuetype="data" />
<param name="trackID" value="1" valuetype="data" />
<param name="trackName" value="video" valuetype="data" />
<param name="trackIndex" value="ignite_480x270_AACAudio_721_1.mpi" valuetype="data" />
</video>
<video src="ignite_320x180_AACAudio_381.mp4" systemBitrate="381027">
<param name="systemBitrate" value="381027" valuetype="data" />
<param name="trackID" value="1" valuetype="data" />
<param name="trackName" value="video" valuetype="data" />
<param name="trackIndex" value="ignite_320x180_AACAudio_381_1.mpi" valuetype="data" />
</video>
</switch>
</body>
</smil>
الحصول على محدد موقع البث
بعد اكتمال الترميز، الخطوة التالية هي جعل الفيديو في أصل الإخراج متاحا للعملاء للتشغيل. يمكنك إنجاز ذلك في خطوتين: أولا، إنشاء محدد موقع البث، والثاني، إنشاء عناوين URL المتدفقة التي يمكن للعملاء استخدامها.
تسمى عملية إنشاء محدد موقع البث النشر. بشكل افتراضي، يكون محدد موقع البث صالحا مباشرة بعد إجراء استدعاءات واجهة برمجة التطبيقات، ويستمر حتى يتم حذفه، ما لم تقم بتكوين أوقات البدء والانتهاء الاختيارية.
عند إنشاء StreamingLocator، ستحتاج إلى تحديد StreamingPolicyName المطلوب. في هذا المثال، سيتم دفق محتوى واضح (أو محتوى غير مشفر) بحيث يتم استخدام نهج التدفق الواضح المحدد مسبقا (PredefinedStreamingPolicy.ClearStreamingOnly).
هام
عند استخدام "Streaming Policy" المخصصة، يجب عليك تصميم مجموعة محدودة من هذه النُهج لحساب خدمة الوسائط الخاص بك، وإعادة استخدامها لـ StreamingLocators كلما دعت الحاجة إلى نفس خيارات التشفير والبروتوكولات. يحتوي حسابك على خدمة الوسائط على حصة لعدد إدخالات "StreamingPolicy" . يجب ألا تنشئ نهج بث جديدة لكل محدد مواقع البث.
تفترض التعليمات البرمجية التالية أنك تقوم باستدعاء الدالة باسم محدد موقع فريد.
private static async Task<StreamingLocator> CreateStreamingLocatorAsync(
IAzureMediaServicesClient client,
string resourceGroup,
string accountName,
string assetName,
string locatorName)
{
StreamingLocator locator = await client.StreamingLocators.CreateAsync(
resourceGroup,
accountName,
locatorName,
new StreamingLocator
{
AssetName = assetName,
StreamingPolicyName = PredefinedStreamingPolicy.ClearStreamingOnly
});
return locator;
}
بينما يناقش النموذج في هذا الموضوع البث، يمكنك استخدام نفس المكالمة لإنشاء محدد موقع البث لتسليم الفيديو عبر التنزيل التدريجي.
الحصول على عناوين URL المتدفقة
الآن بعد أن تم إنشاء محدد موقع البث ، يمكنك الحصول على عناوين URL المتدفقة، كما هو موضح في عناوين URL الخاصة ب GetStreaming. لإنشاء عنوان URL، تحتاج إلى سلسلة اسم مضيف نقطة النهاية المتدفقة ومسار محدد موقع البث . في هذا النموذج، يتم استخدام نقطة نهاية البثالافتراضية. عند إنشاء حساب Media Service لأول مرة، ستكون نقطة النهاية الافتراضية هذه في حالة توقف، لذلك تحتاج إلى استدعاء البدء.
ملاحظة
في هذا الأسلوب، تحتاج إلى اسم محدد الموقع الذي تم استخدامه عند إنشاء Streaming Locator لأصل الإخراج.
private static async Task<IList<string>> GetStreamingUrlsAsync(
IAzureMediaServicesClient client,
string resourceGroupName,
string accountName,
String locatorName)
{
const string DefaultStreamingEndpointName = "default";
IList<string> streamingUrls = new List<string>();
StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(resourceGroupName, accountName, DefaultStreamingEndpointName);
if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running)
{
await client.StreamingEndpoints.StartAsync(resourceGroupName, accountName, DefaultStreamingEndpointName);
}
ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName);
foreach (StreamingPath path in paths.StreamingPaths)
{
UriBuilder uriBuilder = new UriBuilder
{
Scheme = "https",
Host = streamingEndpoint.HostName,
Path = path.Paths[0]
};
streamingUrls.Add(uriBuilder.ToString());
}
return streamingUrls;
}
اختبر مع Azure Media Player اختبر مع Azure Media Player
لاختبار البث، استعن بهذه المقالة Azure Media Player.
ملاحظة
في حال تم استضافة مشغل على موقع https، فتأكد من تحديث عنوان URL إلى "https".
افتح مستعرض ويب، وانتقل إلى https://aka.ms/azuremediaplayer/.
في المربع URL: الصق إحدى قيم عنوان URL المتدفقة التي حصلت عليها من تطبيقك.
يمكنك لصق عنوان URL بتنسيق HLS أو Dash أو Smooth، وسيتحولAzure Media Player إلى بروتوكول تدفق مناسب للتشغيل على جهازك تلقائيا.
اضغط تحديث المشغل.
يمكن استخدام Azure Media Player للاختبار، ولكن يجب ألا يُستخدم في بيئة إنتاج.