লাইভ স্ট্রিমিং

ExoPlayer বেশিরভাগ অ্যাডাপ্টিভ লাইভ স্ট্রিম কোনও বিশেষ কনফিগারেশন ছাড়াই বক্সের বাইরে প্লে করে। আরও বিবরণের জন্য কাজ করে এমন ফর্ম্যাট সংক্রান্ত পৃষ্ঠা দেখুন।

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

লাইভ প্লেব্যাক শনাক্ত ও মনিটর করা

প্রতিবার লাইভ উইন্ডো আপডেট করা হলে, রেজিস্টার করা Player.Listener ইনস্ট্যান্স একটি onTimelineChanged ইভেন্ট পাবে। আপনি নিচে তালিকাভুক্ত এবং নিম্নলিখিত চিত্রে দেখানো বিভিন্ন Player এবং Timeline.Window মেথড কোয়েরি করে বর্তমান লাইভ প্লেব্যাক সম্পর্কে বিবরণ পেতে পারেন।

লাইভ উইন্ডো

  • Player.isCurrentWindowLive থেকে বোঝা যায় যে বর্তমানে চালানো মিডিয়া আইটেমটি লাইভ স্ট্রিম কিনা। লাইভ স্ট্রিম শেষ হয়ে গেলেও এই ভ্যালু True থাকে।
  • Player.isCurrentWindowDynamic থেকে বোঝা যায় যে বর্তমানে চালানো মিডিয়া আইটেম এখনও আপডেট করা হচ্ছে কিনা। যেসব লাইভ স্ট্রিম এখনও শেষ হয়নি সেগুলির ক্ষেত্রে এটি সাধারণত সত্যি হয়। মনে রাখবেন, কিছু ক্ষেত্রে লাইভ স্ট্রিম নয় এমন কন্টেন্টের ক্ষেত্রেও এই ফ্ল্যাগ সত্য হতে পারে।
  • Player.getCurrentLiveOffset বর্তমান রিয়েল টাইম ও প্লেব্যাক পজিশনের (উপলভ্য থাকলে) মধ্যে অফসেট রিটার্ন করে।
  • Player.getDuration বর্তমান লাইভ উইন্ডোর দৈর্ঘ্য দেখায়।
  • Player.getCurrentPosition লাইভ উইন্ডোর শুরু থেকে প্লেব্যাকের আপেক্ষিক পজিশন রিটার্ন করে।
  • Player.getCurrentMediaItem বর্তমান মিডিয়া আইটেম রিটার্ন করে, যেখানে MediaItem.liveConfiguration-এ টার্গেট লাইভ অফসেট ও লাইভ অফসেট অ্যাডজাস্টমেন্ট প্যারামিটারের জন্য অ্যাপ-প্রদানকৃত ওভাররাইড থাকে।
  • Player.getCurrentTimeline একটি Timeline-এ বর্তমান মিডিয়া স্ট্রাকচার রিটার্ন করে। Player.getCurrentMediaItemIndex ও Timeline.getWindow ব্যবহার করে Timeline থেকে বর্তমান Timeline.Window পাওয়া যেতে পারে। এর মধ্যে Window:
    • Window.liveConfiguration-এ টার্গেট লাইভ অফসেট ও লাইভ অফসেট অ্যাডজাস্টমেন্ট প্যারামিটার থাকে। এইসব ভ্যালু মিডিয়াতে থাকা তথ্য এবং MediaItem.liveConfiguration-এ সেট করা অ্যাপ-প্রদানকৃত ওভাররাইডের উপর ভিত্তি করে তৈরি করা হয়।
    • Window.windowStartTimeMs হল Unix Epoch থেকে সেই সময়, যেখান থেকে লাইভ উইন্ডো শুরু হয়।
    • Window.getCurrentUnixTimeMs হল Unix Epoch থেকে বর্তমান রিয়েল-টাইম পর্যন্ত সময়। সার্ভার ও ক্লায়েন্টের মধ্যে পরিচিত ঘড়ির পার্থক্য দ্বারা এই মানটি সংশোধন করা যেতে পারে।
    • Window.getDefaultPositionMs হল লাইভ উইন্ডোতে সেই পজিশন যেখানে প্লেয়ার ডিফল্ট হিসেবে প্লেব্যাক শুরু করবে।

লাইভ স্ট্রিমে খোঁজা

আপনি Player.seekTo ব্যবহার করে লাইভ উইন্ডোর মধ্যে যেকোনও জায়গায় যেতে পারেন। লাইভ উইন্ডোর শুরু থেকে পাস করা পজিশনটি আপেক্ষিক। যেমন, seekTo(0) লাইভ উইন্ডোর শুরুতে নিয়ে যাবে। প্লেয়ারটি, খোঁজা পজিশনে যাওয়ার পরে, খোঁজা পজিশনের মতো একই লাইভ অফসেট রাখার চেষ্টা করবে।

লাইভ উইন্ডোর একটি ডিফল্ট পজিশনও থাকে, যেখান থেকে প্লেব্যাক শুরু হওয়ার কথা থাকে। এই পজিশনটি সাধারণত লাইভ এজের কাছাকাছি কোথাও থাকে। Player.seekToDefaultPosition কল করে আপনি ডিফল্ট পজিশনে যেতে পারবেন।

লাইভ প্লেব্যাক UI

ExoPlayer-এর ডিফল্ট UI কম্পোনেন্ট লাইভ উইন্ডোর সময়সীমা এবং এর মধ্যে বর্তমান প্লেব্যাক পজিশন দেখায়। এর অর্থ হল, লাইভ উইন্ডো আপডেট করা হলে, পজিশনটি প্রতিবার পিছনের দিকে জাম্প করবে। আপনার যদি আলাদা ব্যবহারের প্রয়োজন হয়, যেমন Unix সময় বা বর্তমান লাইভ অফসেট দেখানো, তাহলে আপনি PlayerControlView ফর্ক করতে পারেন এবং আপনার প্রয়োজন অনুসারে এটি পরিবর্তন করতে পারেন।

লাইভ প্লেব্যাক প্যারামিটার কনফিগার করা

লাইভ এজের থেকে প্লেব্যাক পজিশনের অফসেট কন্ট্রোল করতে ExoPlayer কিছু প্যারামিটার ব্যবহার করে এবং এই অফসেট অ্যাডজাস্ট করতে প্লেব্যাক স্পিডের রেঞ্জ ব্যবহার করা যেতে পারে।

ExoPlayer এই প্যারামিটারগুলির ভ্যালু তিনটি জায়গা থেকে পায়, অগ্রাধিকারের নিম্নক্রম অনুসারে (প্রথম যে ভ্যালু পাওয়া যায় সেটি ব্যবহার করা হয়):

  • MediaItem.Builder.setLiveConfiguration-এ পাস করা MediaItem ভ্যালু প্রতি।
  • DefaultMediaSourceFactory-এ গ্লোবাল ডিফল্ট ভ্যালু সেট করা আছে।
  • মিডিয়া থেকে সরাসরি পড়া ভ্যালু।

Kotlin

// Global settings.
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000))
    .build()

// Per MediaItem settings.
val mediaItem =
  MediaItem.Builder()
    .setUri(mediaUri)
    .setLiveConfiguration(
      MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build()
    )
    .build()
player.setMediaItem(mediaItem)

জাভা

// Global settings.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000))
        .build();

// Per MediaItem settings.
MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(mediaUri)
        .setLiveConfiguration(
            new MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build())
        .build();
player.setMediaItem(mediaItem);

উপলভ্য কনফিগারেশন ভ্যালুগুলি হল:

  • targetOffsetMs: টার্গেট লাইভ অফসেট। সম্ভব হলে, প্লেয়ার প্লেব্যাকের সময় এই লাইভ অফসেটের কাছাকাছি থাকার চেষ্টা করবে।
  • minOffsetMs: লাইভ অফসেটের ন্যূনতম অনুমোদিত সময়সীমা। বর্তমান নেটওয়ার্কের কন্ডিশন অনুযায়ী অফসেট অ্যাডজাস্ট করার সময়ও, প্লেয়ার প্লেব্যাকের সময় এই অফসেটের নিচে যাওয়ার চেষ্টা করবে না।
  • maxOffsetMs: লাইভ অফসেটের সর্বাধিক অনুমোদিত সীমা। বর্তমান নেটওয়ার্কের কন্ডিশন অনুযায়ী অফসেট অ্যাডজাস্ট করার সময়ও, প্লেব্যাক চলাকালীন প্লেয়ার এই অফসেটের উপরে যাওয়ার চেষ্টা করবে না।
  • minPlaybackSpeed: টার্গেট লাইভ অফসেটে পৌঁছানোর চেষ্টা করার সময় প্লেয়ার ফল ব্যাক করার জন্য ন্যূনতম প্লেব্যাক স্পিড ব্যবহার করতে পারে।
  • maxPlaybackSpeed: টার্গেট লাইভ অফসেটে পৌঁছানোর চেষ্টা করার সময় প্লেয়ার যে সর্বাধিক প্লেব্যাক স্পিড ব্যবহার করতে পারে।

প্লেব্যাক স্পিড অ্যাডজাস্টমেন্ট

লো-লেটেন্সি লাইভ স্ট্রিম চালানোর সময়, ExoPlayer প্লেব্যাক স্পিড সামান্য পরিবর্তন করে লাইভ অফসেট অ্যাডজাস্ট করে। প্লেয়ার মিডিয়া বা অ্যাপের দেওয়া টার্গেট লাইভ অফসেট ম্যাচ করার চেষ্টা করবে, তবে পরিবর্তিত নেটওয়ার্ক কন্ডিশনের সাথেও মানিয়ে নেওয়ার চেষ্টা করবে। যেমন, প্লেব্যাকের সময় আবার বাফার হলে, লাইভ এজ থেকে আরও দূরে সরে যাওয়ার জন্য প্লেয়ার প্লেব্যাক কিছুটা ধীরে করে দেবে। নেটওয়ার্ক যদি আবার লাইভ এজের কাছাকাছি প্লে করার মতো যথেষ্ট স্থিতিশীল হয়ে যায়, তাহলে প্লেয়ার প্লেব্যাক স্পিড বাড়িয়ে টার্গেট লাইভ অফসেটের দিকে এগিয়ে যাবে।

অটোমেটিক প্লেব্যাক স্পিড অ্যাডজাস্টমেন্ট না চাইলে, minPlaybackSpeed ও maxPlaybackSpeed প্রপার্টি 1.0f হিসেবে সেট করে এটি বন্ধ করা যেতে পারে। একইভাবে, 1.0f ছাড়া অন্য কোনও ভ্যালুতে এগুলি স্পষ্টভাবে সেট করে, কম লেটেন্সি না থাকা লাইভ স্ট্রিমের জন্য এটি চালু করা যেতে পারে। এইসব প্রপার্টি কীভাবে সেট করা যায় সেই সম্পর্কে আরও বিবরণ পেতে উপরে কনফিগারেশন বিভাগ দেখুন।

প্লেব্যাক স্পিড অ্যাডজাস্টমেন্ট অ্যালগরিদম কাস্টমাইজ করা

স্পিড অ্যাডজাস্টমেন্ট চালু করা থাকলে, LivePlaybackSpeedControl থেকে কী কী অ্যাডজাস্টমেন্ট করা হয়েছে তা বোঝা যায়। কাস্টম LivePlaybackSpeedControl প্রয়োগ করা অথবা ডিফল্ট প্রয়োগ কাস্টমাইজ করা সম্ভব, যা হল DefaultLivePlaybackSpeedControl। দুটি ক্ষেত্রেই, প্লেয়ার তৈরি করার সময় ইনস্ট্যান্স সেট করা যেতে পারে:

Kotlin

val player =
  ExoPlayer.Builder(context)
    .setLivePlaybackSpeedControl(
      DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build()
    )
    .build()

জাভা

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setLivePlaybackSpeedControl(
            new DefaultLivePlaybackSpeedControl.Builder()
                .setFallbackMaxPlaybackSpeed(1.04f)
                .build())
        .build();

DefaultLivePlaybackSpeedControl-এর প্রাসঙ্গিক কাস্টমাইজেশন প্যারামিটারগুলি হল:

  • fallbackMinPlaybackSpeed ও fallbackMaxPlaybackSpeed: মিডিয়া বা অ্যাপ-প্রদানকারী MediaItem কোনও সীমা নির্ধারণ না করলে, অ্যাডজাস্টমেন্টের জন্য ব্যবহার করা যেতে পারে এমন ন্যূনতম ও সর্বাধিক প্লেব্যাক স্পিড।
  • proportionalControlFactor: স্পিড অ্যাডজাস্টমেন্ট কতটা মসৃণ হবে তা নিয়ন্ত্রণ করে। A বেশি ভ্যালু অ্যাডজাস্টমেন্টকে আরও আকস্মিক ও প্রতিক্রিয়াশীল করে তোলে, তবে এটি আরও বেশি করে শ্রবণযোগ্য হওয়ার সম্ভাবনা থাকে। মান কম হলে স্পিডের মধ্যে ট্রানজিশন আরও মসৃণ হয়, তবে এর ফলে স্পিড কমে যায়।
  • targetLiveOffsetIncrementOnRebufferMs: আবার বাফারিং হলে, আরও সতর্কতার সাথে প্রসেস করার জন্য এই ভ্যালু টার্গেট লাইভ অফসেটে যোগ করা হয়। মান ০ হিসেবে সেট করে এই ফিচার বন্ধ করা যেতে পারে।
  • minPossibleLiveOffsetSmoothingFactor: একটি এক্সপোনেনশিয়াল স্মুথিং ফ্যাক্টর যা বর্তমানে বাফার করা মিডিয়ার উপর ভিত্তি করে সম্ভাব্য ন্যূনতম লাইভ অফসেট ট্র্যাক করতে ব্যবহার করা হয়। ১-এর খুব কাছাকাছি ভ্যালু মানে হল যে এস্টিমেশন আরও সতর্ক এবং নেটওয়ার্কের কন্ডিশন উন্নত হলে অ্যাডজাস্ট হতে বেশি সময় লাগতে পারে, যেখানে কম ভ্যালু মানে হল যে এস্টিমেশন আরও দ্রুত অ্যাডজাস্ট হবে, তবে রিবাফারিং হওয়ার ঝুঁকি বেশি থাকবে।

BehindLiveWindowException এবং ERROR_CODE_BEHIND_LIVE_WINDOW

প্লেব্যাক পজিশন লাইভ উইন্ডোর থেকে পিছিয়ে যেতে পারে, যেমন, প্লেয়ার যদি যথেষ্ট দীর্ঘ সময় ধরে পজ বা বাফারিং করা হয়। এটি ঘটলে, প্লেব্যাক সফল হবে না এবং ERROR_CODE_BEHIND_LIVE_WINDOW ত্রুটি কোড সহ একটি ব্যতিক্রম Player.Listener.onPlayerError-এর মাধ্যমে রিপোর্ট করা হবে। ডিফল্ট পজিশনে প্লেব্যাক আবার চালু করার মাধ্যমে অ্যাপ্লিকেশন কোড এই ধরনের সমস্যা সমাধান করতে পারে। ডেমো অ্যাপের PlayerActivity এই পদ্ধতির উদাহরণ।

Kotlin

override fun onPlayerError(error: PlaybackException) {
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the live edge.
    player.seekToDefaultPosition()
    player.prepare()
  } else {
    // Handle other errors
  }
}

জাভা

@Override
public void onPlayerError(PlaybackException error) {
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the live edge.
    player.seekToDefaultPosition();
    player.prepare();
  } else {
    // Handle other errors
  }
}