প্লেয়ার ইন্টারফেস

প্লেয়ার হল আপনার অ্যাপের এমন একটি কম্পোনেন্ট যা মিডিয়া আইটেম প্লেব্যাক করার সুবিধা দেয়। Media3 Player ইন্টারফেস সাধারণত প্লেয়ারের মাধ্যমে ম্যানেজ করা ফাংশনালিটির জন্য একটি আউটলাইন সেট-আপ করে। এর মধ্যে এগুলি অন্তর্ভুক্ত:

  • প্লেব্যাক কন্ট্রোলকে প্রভাবিত করে, যেমন চালানো, পজ করা ও খোঁজা
  • বর্তমানে চলছে এমন মিডিয়ার প্রপার্টি কোয়েরি করা, যেমন প্লেব্যাক পজিশন
  • মিডিয়া আইটেমের প্লেলিস্ট/কিউ ম্যানেজ করা
  • শাফেল, রিপিট, স্পিড ও ভলিউমের মতো প্লেব্যাক প্রপার্টি কনফিগার করা
  • স্ক্রিনে ভিডিও রেন্ডার করা

Media3 Player ইন্টারফেসের একটি প্রয়োগও প্রদান করে, যাকে ExoPlayer বলা হয়।

কম্পোনেন্টগুলির মধ্যে একটি সাধারণ ইন্টারফেস

Media3-এর বিভিন্ন কম্পোনেন্ট প্লেয়ার ইন্টারফেস প্রয়োগ করে, যেমন:

কম্পোনেন্ট বিবরণ ও আচরণ সংক্রান্ত নোট
ExoPlayer মিডিয়া প্লেয়ার API এবং Player ইন্টারফেসের ডিফল্ট প্রয়োগ।
MediaController প্লেব্যাক কমান্ড পাঠানোর জন্য MediaSession-এর সাথে ইন্টার‍্যাক্ট করে। যদি আপনার Player এবং MediaSession Service Activity বা Fragment থেকে আলাদা হয়, যেখানে আপনার প্লেয়ারের UI থাকে, তাহলে আপনি MediaController-কে আপনার UI কম্পোনেন্টের প্লেয়ার হিসেবে অ্যাসাইন করতে পারবেন, যেমন PlayerView বা Player কম্পোজ করা যায় এমন। প্লেব্যাক ও প্লেলিস্ট মেথড কল আপনার MediaSession-এর মাধ্যমে Player-এ পাঠানো হয়।
MediaBrowser MediaController-এর দেওয়া কার্যকারিতা ছাড়াও, উপলভ্য মিডিয়া কন্টেন্ট ব্রাউজ করতে MediaLibrarySession-এর সাথে ইন্টার‍্যাক্ট করে।
SimpleBasePlayer ন্যূনতম সংখ্যক মেথড ইমপ্লিমেন্ট করার জন্য Player ইমপ্লিমেন্টেশন। আপনি MediaSession-এর সাথে কানেক্ট করতে চান এমন কাস্টম প্লেয়ার ব্যবহার করার সময় এটি সহায়ক।
ForwardingSimpleBasePlayer SimpleBasePlayer-এর মতো একই ধরনের সামঞ্জস্যপূর্ণ আচরণ কাস্টমাইজ করার অনুমতি দেওয়ার সময় প্লেব্যাক অপারেশন অন্য Player-এ ফরওয়ার্ড করার জন্য ডিজাইন করা একটি SimpleBasePlayer সাবক্লাস। নির্দিষ্ট প্লেব্যাক অপারেশন বন্ধ করতে বা পরিবর্তন করতে এই ক্লাস ব্যবহার করুন।
RemoteCastPlayer রিমোট কাস্ট রিসিভার অ্যাপে প্লেব্যাক কন্ট্রোল করার জন্য Player প্রয়োগ করা।
CastPlayer লোকাল ও রিমোট Cast প্লেব্যাক কন্ট্রোল করার জন্য Player প্রয়োগ করা।

MediaSession, Player ইন্টারফেস প্রয়োগ না করলেও, এটি তৈরি করার সময় Player প্রয়োজন হয়। এর উদ্দেশ্য হল, অন্যান্য প্রসেস বা থ্রেড থেকে Player অ্যাক্সেস করার সুবিধা দেওয়া।

Media3 প্লেব্যাক আর্কিটেকচার

আপনার কাছে Player-এর অ্যাক্সেস থাকলে, প্লেব্যাক কমান্ড ইস্যু করার জন্য আপনাকে সরাসরি এর মেথড কল করতে হবে। আপনি প্লেব্যাক বিজ্ঞাপন দিতে এবং MediaSession প্রয়োগ করে এক্সটার্নাল সোর্সকে প্লেব্যাক কন্ট্রোল করার অনুমতি দিতে পারবেন। এইসব এক্সটার্নাল সোর্স MediaController প্রয়োগ করে, যা মিডিয়া সেশনের সাথে কানেক্ট করা এবং প্লেব্যাক কমান্ড সংক্রান্ত অনুরোধ ইস্যু করার ব্যাপারে সাহায্য করে।

ব্যাকগ্রাউন্ডে মিডিয়া চালানোর সময়, আপনাকে মিডিয়া সেশন ও প্লেয়ারকে MediaSessionService বা MediaLibraryService-এর মধ্যে রাখতে হবে, যা ফোরগ্রাউন্ড পরিষেবা হিসেবে চলে। আপনি এটি করলে, প্লেব্যাক কন্ট্রোলের জন্য UI থাকা আপনার অ্যাপের অ্যাক্টিভিটি থেকে আপনার প্লেয়ারকে আলাদা করতে পারবেন। এর জন্য আপনাকে মিডিয়া কন্ট্রোলার ব্যবহার করতে হতে পারে।

মিডিয়া অ্যাপ আর্কিটেকচারে Media3 প্লেব্যাক কম্পোনেন্ট কীভাবে ফিট করে তা দেখানো একটি ডায়াগ্রাম।
ছবি ১: Media3-এর আর্কিটেকচারে Player ইন্টারফেস একটি গুরুত্বপূর্ণ ভূমিকা পালন করে।

প্লেয়ার স্টেট

Player ইন্টারফেস প্রয়োগকারী মিডিয়া প্লেয়ারের স্ট্যাটাসে প্রধানত ৪টি বিভাগের তথ্য থাকে:

  1. প্লেব্যাক স্টেট
  2. মিডিয়া আইটেমের প্লেলিস্ট
    • প্লেব্যাকের জন্য MediaItemটি ইন্সট্যান্সের একটি সিকোয়েন্স।
    • getCurrentTimeline()-এর মাধ্যমে রিট্রিভ করা
    • Player ইনস্ট্যান্স প্লেলিস্ট অপারেশন পদ্ধতি প্রদান করতে পারে, যেমন যোগ করা বা সরানো MediaItem এবং কনভেনিয়েন্স পদ্ধতি, যেমন getCurrentMediaItem()।
  3. প্রপার্টি চালান/পজ করুন, যেমন:
    • playWhenReady: সম্ভব হলে ব্যবহারকারী মিডিয়া চালাতে চান নাকি সেটি পজ করে রাখতে চান সেই সংক্রান্ত ইঙ্গিত
    • প্লেব্যাক সাপ্রেশনের কারণ: প্লেব্যাক সাপ্রেস করা হয়ে থাকলে, তার কারণের ইঙ্গিত। এটি প্রযোজ্য হলে, এমনকি playWhenReady true হলেও এটি প্রযোজ্য হবে
    • isPlaying: প্লেয়ার বর্তমানে চলছে কিনা তার ইঙ্গিত, যা শুধুমাত্র true হবে যদি প্লেব্যাক স্টেট STATE_READY হয়, playWhenReady true হয় এবং প্লেব্যাক চাপা না দেওয়া হয়
  4. প্লেব্যাক পজিশন, এর মধ্যে রয়েছে:

এছাড়াও, Player ইন্টারফেসের মাধ্যমে উপলভ্য ট্র্যাক, মিডিয়া মেটাডেটা, প্লেব্যাকের স্পিড, ভলিউম এবং অন্যান্য প্লেব্যাকের সহায়ক প্রপার্টি অ্যাক্সেস করা যায়।

পরিবর্তন সম্পর্কে শুনুন

Player.Listener ব্যবহার করে Player-এ হওয়া পরিবর্তন শুনুন। কীভাবে লিসনার তৈরি ও ব্যবহার করতে হয় সেই বিষয়ে বিস্তারিত জানতে, ExoPlayer ডকুমেন্টেশনে প্লেয়ার ইভেন্ট দেখুন।

মনে রাখবেন, সাধারণ প্লেব্যাক প্রগ্রেশন ট্র্যাক করার জন্য লিসনার ইন্টারফেসে কোনও কলব্যাক অন্তর্ভুক্ত থাকে না। প্লেব্যাকের অগ্রগতি ক্রমাগত মনিটর করতে, যেমন, প্রগ্রেস বার UI সেট-আপ করতে, আপনাকে সঠিক ইন্টারভ্যালে বর্তমান পজিশন কোয়েরি করতে হবে।

Kotlin

fun checkPlaybackPosition(delayMs: Long): Boolean =
  handler.postDelayed(
    {
      val currentPosition = player.currentPosition
      // Update UI based on currentPosition
      checkPlaybackPosition(delayMs)
    },
    delayMs,
  )

জাভা

boolean checkPlaybackPosition(long delayMs) {
  return handler.postDelayed(
      () -> {
        long currentPosition = player.getCurrentPosition();
        // Update UI based on currentPosition
        checkPlaybackPosition(delayMs);
      },
      delayMs);
}

প্লেব্যাক কন্ট্রোল করা

Player ইন্টারফেস, প্লেব্যাক কন্ট্রোল করার জন্য বিভিন্ন উপায় অফার করে:

কাস্টম Player প্রয়োগ

কাস্টম প্লেয়ার তৈরি করতে, Media3-এ অন্তর্ভুক্ত SimpleBasePlayer ব্যবহার করতে পারেন। এই ক্লাসটি Player ইন্টারফেসের একটি বেস ইমপ্লিমেন্টেশন প্রদান করে যাতে আপনাকে ন্যূনতম সংখ্যক পদ্ধতি প্রয়োগ করতে হয়।

getState() পদ্ধতি ওভাররাইড করার মাধ্যমে শুরু করুন। এই পদ্ধতি কল করা হলে, এর মধ্যে থাকা বর্তমান প্লেয়ারের অবস্থা পূরণ করা উচিত:

  • উপলভ্য কমান্ডের সেট
  • প্লেব্যাক প্রপার্টি, যেমন প্লেব্যাক স্টেট STATE_READY হলে প্লেয়ারকে প্লে করা শুরু করতে হবে কিনা, বর্তমানে চালানো মিডিয়া আইটেমের ইন্ডেক্স এবং বর্তমান আইটেমের মধ্যে প্লেব্যাক পজিশন

Kotlin

class CustomPlayer(looper: Looper) : SimpleBasePlayer(looper) {
  override fun getState(): State {
    return State.Builder()
      .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle
      // Configure additional playback properties
      .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
      .setCurrentMediaItemIndex(0)
      .setContentPositionMs(0)
      .build()
  }
}

জাভা

private static final class CustomPlayer extends SimpleBasePlayer {
  public CustomPlayer(Looper looper) {
    super(looper);
  }

  @Override
  protected State getState() {
    return new State.Builder()
        .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle
        // Configure additional playback properties
        .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
        .setCurrentMediaItemIndex(0)
        .setContentPositionMs(0)
        .build();
  }
}

SimpleBasePlayer নিশ্চিত করবে যে State-এর মধ্যে স্টেট ভ্যালুর সঠিক কম্বিনেশন আছে। এছাড়াও, এটি লিসনারদের ম্যানেজ করবে এবং স্টেট পরিবর্তন সম্পর্কে লিসনারদের জানাবে। আপনাকে ম্যানুয়ালি কোনও স্টেট আপডেট ট্রিগার করতে হলে, invalidateState() কল করুন।

getState() পদ্ধতি ছাড়াও, প্লেয়ার উপলভ্য বলে ঘোষণা করেছে এমন কমান্ডের জন্য ব্যবহৃত পদ্ধতিগুলিই আপনাকে প্রয়োগ করতে হবে। আপনি যে ফাংশনালিটি প্রয়োগ করতে চান তার সাথে সম্পর্কিত ওভাররাইড করা যায় এমন হ্যান্ডলার মেথড খুঁজুন। যেমন, handleSeek() মেথড ওভাররাইড করে COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM ও COMMAND_SEEK_TO_NEXT_MEDIA_ITEM-এর মতো অপারেশন করা যায়।

Player প্রয়োগ করা পদ্ধতি পরিবর্তন করা

সম্পূর্ণ কাস্টম Player তৈরি করার পরিবর্তে, আপনি আগে থেকে থাকা Player-এর স্টেট ও আচরণ পরিবর্তন করতে ForwardingSimpleBasePlayer ব্যবহার করতে পারবেন। আরও বিবরণের জন্য কাস্টমাইজেশন পৃষ্ঠায় দেওয়া নির্দেশিকা দেখুন।