Skip to content
SiteEmail

Prysm comes with its own Media Decoder. You can read more details about the native decoder here.

As of UE 4.27, the engine comes with the Bink Media plugin by default. Prysm and Bink can be utilized together in a fairly straightforward fashion with minimal code.

The easiest way to add a Bink video playback to your UI, is by using a Live View. The general idea is to:

  • Have a Render Target
  • Create a <video> element in your HTML page, with an Unreal asset source path to your Render Target
    • For example "TextureRenderTarget2D'/Game/MapAssets/BinkMediaPlayer/BinkVideoRT.BinkVideoRT'"
  • Create a UBinkMediaPlayer object and configure its settings
  • Call UBinkMediaPlayer::Draw on each Tick

Here is an example code we use for our BinkVideoMap sample:

  1. Subscribe to the ReadyForBindings event

    ACoherentSampleBinkVideoPlayerHUD::ACoherentSampleBinkVideoPlayerHUD()
    : currenttime(0.f)
    , duration(0.f)
    , volume(1.f)
    , paused(false)
    , muted(false)
    , loop(false)
    , View(nullptr)
    , MediaPlayer(nullptr)
    , BinkTextureRT(nullptr)
    , ModelSyncNeeded(false)
    , VideoEnded(false)
    {
    check(CohtmlHUD);
    CohtmlHUD->ReadyForBindings.AddDynamic(this, &ACoherentSampleBinkVideoPlayerHUD::BindUI);
    }
  2. Create and initialize a UBinkMediaPlayer object when your ReadyForBindings delegate gets executed:

    void ACoherentSampleBinkVideoPlayerHUD::BindUI()
    {
    MediaPlayer = NewObject<UBinkMediaPlayer>();
    MediaPlayer->URL = TEXT("./Movies/SampleVideo_1280x720_vp8.bk2");
    MediaPlayer->BinkSoundTrack = BMASM_Bink_Sound_Simple;
    MediaPlayer->Looping = false;
    BinkTextureRT = LoadObject<UTextureRenderTarget2D>(nullptr, TEXT("/Game/MapAssets/BinkMediaPlayer/BinkVideoRT. BinkVideoRT"));
    BinkTextureRT->RenderTargetFormat = RTF_RGBA8;
    BinkTextureRT->SRGB = false;
    BinkTextureRT->bForceLinearGamma = false;
    BinkTextureRT->ClearColor = FLinearColor::Black;
    // By this point there will be a valid Viewport even in a packaged game
    FVector2D ViewportSize;
    GEngine->GameViewport->GetViewportSize(ViewportSize);
    BinkTextureRT->SizeX = ViewportSize.X;
    BinkTextureRT->SizeY = ViewportSize.Y;
    BinkTextureRT->UpdateResource();
    MediaPlayer->InitializePlayer();
    duration = MediaPlayer->GetDuration().GetTotalSeconds();
    View = CohtmlHUD->GetView();
    check(View);
    View->CreateModel("BinkVideoPlayerHUDModel", this);
    View->SynchronizeModels();
    UE_LOG(LogCoherentSample, Log, TEXT("UI is bound!"));
    }
  3. Call UBinkMediaPlayer::Draw each Tick

    void ACoherentSampleBinkVideoPlayerHUD::Tick(float DeltaTime)
    {
    if (!View)
    {
    return;
    }
    FVector2D ViewportSize;
    GEngine->GameViewport->GetViewportSize(ViewportSize);
    if (BinkTextureRT->SizeX != ViewportSize.X || BinkTextureRT->SizeY != ViewportSize.Y)
    {
    BinkTextureRT->SizeX = ViewportSize.X;
    BinkTextureRT->SizeY = ViewportSize.Y;
    }
    if (!BinkTextureRT->HasPendingRenderResourceInitialization())
    {
    MediaPlayer->Draw(BinkTextureRT);
    }
    currenttime = MediaPlayer->GetTime().GetTotalSeconds();
    if (ModelSyncNeeded)
    {
    View->SynchronizeModels();
    }
    // UBinkMediaPlayer's OnMediaReachedEnd event seems to be buggy,
    // as it gets fired even when calling UBinkMediaPlayer::Seek at
    // a time before the end of a given video, so we handle this ourselves.
    if (MediaPlayer->GetTime() == MediaPlayer->GetDuration() && !VideoEnded)
    {
    OnMediaReachedEnd();
    VideoEnded = true;
    }
    }

With this approach, if you have an in-world View, you will be able to play Bink videos in-world as well.

If you want to create UI video controls such as volume, seeking, sound, playback, etc., you can expose the UBinkMediaPlayer APIs to Prysm.

We have a sample map demonstrating this implementation under CoherentSample/Content/Maps/BinkVideoMap.umap within the CoherentSample project. The relevant source code is located in the CoherentSample/Source/CoherentSample/BinkVideoPlayer directory.