جارٍ استرداد البيانات الوصفية
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
أثناء التشغيل
يمكن استرداد البيانات الوصفية للوسائط أثناء التشغيل بطرق متعددة. تشير رسالة الأشكال البيانية
الأكثر وضوحًا هو الاستماع إلى
حدث واحد (Player.Listener#onMediaMetadataChanged
) سيوفر ذلك
كائن MediaMetadata
للاستخدام، ويحتوي على حقول مثل title
albumArtist
بدلاً من ذلك، يؤدي الاتصال بالرقم Player#getMediaMetadata
إلى إرجاع النتيجة نفسها
الخاص بك.
Kotlin
override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {
mediaMetadata.title?.let(::handleTitle)
}
Java
@Override
public void onMediaMetadataChanged(MediaMetadata mediaMetadata) {
if (mediaMetadata.title != null) {
handleTitle(mediaMetadata.title);
}
}
إذا كان تطبيقك يحتاج إلى الوصول إلى عناصر Metadata.Entry
محدَّدة، يجب عندها
يجب أن يتم الاستماع إلى Player.Listener#onMetadata
(للبيانات الوصفية الديناميكية التي يتم إرسالها
أثناء التشغيل). بدلاً من ذلك، إذا كانت هناك حاجة إلى إلقاء نظرة على بيانات التعريف الثابتة،
يمكن الوصول إليه من خلال TrackSelections#getFormat
.
تتم تعبئة Player#getMediaMetadata
من كلا المصدرَين.
بدون تشغيل
إذا لم تكن هناك حاجة إلى التشغيل، فمن الأفضل استخدام
MetadataRetriever
لاستخراج البيانات الوصفية لتجنُّب الحاجة إلى
إنشاء لاعب وإعداده.
Kotlin
suspend fun retrievingMetadataRetrieveMetadataWithoutPlayback(
context: Context,
mediaItem: MediaItem,
) {
try {
MetadataRetriever.Builder(context, mediaItem).build().use { metadataRetriever ->
val trackGroups = metadataRetriever.retrieveTrackGroups().await()
val timeline = metadataRetriever.retrieveTimeline().await()
val durationUs = metadataRetriever.retrieveDurationUs().await()
handleMetadata(trackGroups, timeline, durationUs)
}
} catch (e: IOException) {
handleFailure(e)
}
}
Java
try (MetadataRetriever metadataRetriever =
new MetadataRetriever.Builder(context, mediaItem).build()) {
ListenableFuture<TrackGroupArray> trackGroupsFuture = metadataRetriever.retrieveTrackGroups();
ListenableFuture<Timeline> timelineFuture = metadataRetriever.retrieveTimeline();
ListenableFuture<Long> durationUsFuture = metadataRetriever.retrieveDurationUs();
ListenableFuture<List<Object>> allFutures =
Futures.allAsList(trackGroupsFuture, timelineFuture, durationUsFuture);
Futures.addCallback(
allFutures,
new FutureCallback<List<Object>>() {
@Override
public void onSuccess(List<Object> result) {
handleMetadata(
Futures.getUnchecked(trackGroupsFuture),
Futures.getUnchecked(timelineFuture),
Futures.getUnchecked(durationUsFuture));
}
@Override
public void onFailure(Throwable t) {
handleFailure(t);
}
},
executor);
}
الصور الحيّة
ومن الممكن أيضًا استخراج البيانات الوصفية للصور الحيّة، بما في ذلك الإزاحة
أطوال الصورة وأجزاء الفيديو في الملف.
بالنسبة إلى الصور الحيّة، تمّ الحصول على TrackGroupArray
من خلال MetadataRetriever
.
يحتوي على TrackGroup
مع Format
واحد يشتمل على
إدخال البيانات الوصفية لـ MotionPhotoMetadata
Kotlin
0.until(trackGroups.length)
.asSequence()
.mapNotNull { trackGroups[it].getFormat(0).metadata }
.filter { metadata -> metadata.length() == 1 }
.map { metadata -> metadata[0] }
.filterIsInstance<MotionPhotoMetadata>()
.forEach(::handleMotionPhotoMetadata)
Java
for (int i = 0; i < trackGroups.length; i++) {
TrackGroup trackGroup = trackGroups.get(i);
Metadata metadata = trackGroup.getFormat(0).metadata;
if (metadata != null && metadata.length() == 1) {
Metadata.Entry metadataEntry = metadata.get(0);
if (metadataEntry instanceof MotionPhotoMetadata) {
MotionPhotoMetadata motionPhotoMetadata = (MotionPhotoMetadata) metadataEntry;
handleMotionPhotoMetadata(motionPhotoMetadata);
}
}
}
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-08-01 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-08-01 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["# Retrieving metadata\n\nDuring playback\n---------------\n\nThe metadata of the media can be retrieved during playback in multiple ways. The\nmost straightforward is to listen for the\n`Player.Listener#onMediaMetadataChanged` event; this will provide a\n[`MediaMetadata`](/reference/androidx/media3/common/MediaMetadata) object for use, which has fields such as `title` and\n`albumArtist`. Alternatively, calling `Player#getMediaMetadata` returns the same\nobject. \n\n### Kotlin\n\n```kotlin\noverride fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {\n mediaMetadata.title?.let(::handleTitle)\n}\n```\n\n### Java\n\n```java\n@Override\npublic void onMediaMetadataChanged(MediaMetadata mediaMetadata) {\n if (mediaMetadata.title != null) {\n handleTitle(mediaMetadata.title);\n }\n}\n```\n\n\u003cbr /\u003e\n\nIf your app needs access to specific [`Metadata.Entry`](/reference/androidx/media3/common/Metadata.Entry) objects, then it\nshould listen to `Player.Listener#onMetadata` (for dynamic metadata delivered\nduring playback). Alternatively, if there is a need to look at static metadata,\nthis can be accessed through the `TrackSelections#getFormat`.\n`Player#getMediaMetadata` is populated from both of these sources.\n\nWithout playback\n----------------\n\nIf playback is not needed, it is more efficient to use the\n[`MetadataRetriever`](/reference/androidx/media3/exoplayer/MetadataRetriever) to extract the metadata because it avoids having to\ncreate and prepare a player. \n\n### Kotlin\n\n```kotlin\nsuspend fun retrievingMetadataRetrieveMetadataWithoutPlayback(\n context: Context,\n mediaItem: MediaItem,\n) {\n try {\n MetadataRetriever.Builder(context, mediaItem).build().use { metadataRetriever -\u003e\n val trackGroups = metadataRetriever.retrieveTrackGroups().await()\n val timeline = metadataRetriever.retrieveTimeline().await()\n val durationUs = metadataRetriever.retrieveDurationUs().await()\n handleMetadata(trackGroups, timeline, durationUs)\n }\n } catch (e: IOException) {\n handleFailure(e)\n }\n}\n```\n\n### Java\n\n```java\ntry (MetadataRetriever metadataRetriever =\n new MetadataRetriever.Builder(context, mediaItem).build()) {\n ListenableFuture\u003cTrackGroupArray\u003e trackGroupsFuture = metadataRetriever.retrieveTrackGroups();\n ListenableFuture\u003cTimeline\u003e timelineFuture = metadataRetriever.retrieveTimeline();\n ListenableFuture\u003cLong\u003e durationUsFuture = metadataRetriever.retrieveDurationUs();\n ListenableFuture\u003cList\u003cObject\u003e\u003e allFutures =\n Futures.allAsList(trackGroupsFuture, timelineFuture, durationUsFuture);\n Futures.addCallback(\n allFutures,\n new FutureCallback\u003cList\u003cObject\u003e\u003e() {\n @Override\n public void onSuccess(List\u003cObject\u003e result) {\n handleMetadata(\n Futures.getUnchecked(trackGroupsFuture),\n Futures.getUnchecked(timelineFuture),\n Futures.getUnchecked(durationUsFuture));\n }\n\n @Override\n public void onFailure(Throwable t) {\n handleFailure(t);\n }\n },\n executor);\n}\n```\n\n\u003cbr /\u003e\n\nMotion photos\n-------------\n\n| **Note:** For motion photo **playback** , see [Media Items](/media/media3/exoplayer/images#motion-photos) and for motion photo **format support** , see [Supported formats](/media/media3/exoplayer/supported-formats#images).\n\nIt is also possible to extract motion photo metadata, including the offsets and\nlengths of the image and video parts of the file.\n\nFor motion photos, the `TrackGroupArray` obtained with the `MetadataRetriever`\ncontains a `TrackGroup` with a single `Format` enclosing a\n[`MotionPhotoMetadata`](/reference/androidx/media3/extractor/metadata/mp4/MotionPhotoMetadata) metadata entry. \n\n### Kotlin\n\n```kotlin\n0.until(trackGroups.length)\n .asSequence()\n .mapNotNull { trackGroups[it].getFormat(0).metadata }\n .filter { metadata -\u003e metadata.length() == 1 }\n .map { metadata -\u003e metadata[0] }\n .filterIsInstance\u003cMotionPhotoMetadata\u003e()\n .forEach(::handleMotionPhotoMetadata)\n```\n\n### Java\n\n```java\nfor (int i = 0; i \u003c trackGroups.length; i++) {\n TrackGroup trackGroup = trackGroups.get(i);\n Metadata metadata = trackGroup.getFormat(0).metadata;\n if (metadata != null && metadata.length() == 1) {\n Metadata.Entry metadataEntry = metadata.get(0);\n if (metadataEntry instanceof MotionPhotoMetadata) {\n MotionPhotoMetadata motionPhotoMetadata = (MotionPhotoMetadata) metadataEntry;\n handleMotionPhotoMetadata(motionPhotoMetadata);\n }\n }\n}\n```\n\n\u003cbr /\u003e"]]