Skip to content

Adding video with a code-first approach #200

@Venthe

Description

@Venthe

Hey,
I am unable to add video with the code-first approach. What I am trying to do is to load and use an arbitrary file during a runtime.

Please note, there are several issues with my code; all described below. Also, this is the first couple of hours with Stride; I am a dev by trade - just not in a game dev, and not in c#. The closest I've got is:

var videoAsset = new VideoAsset();
videoAsset.Source = @"<AbsolutePathToTheNewRoot>/Movies/Trailer.bik";
videoAsset.Width = 100;
videoAsset.Height = 100;
var location = new UFile("Movies/Trailer");
var assetItem = new AssetItem(location, videoAsset);
assetItem.SourceFolder = @"<AbsolutePathToTheNewRoot>";
var logger = new LoggerResult();
var indexName = VirtualFileSystem.ApplicationDatabaseIndexName;
var builder = new Stride.Core.BuildEngine.Builder(logger, BuildPath, indexName) { BuilderName = "TestBuilder" };

var assetCompilerContext = new AssetCompilerContext();

var result = new VideoAssetCompiler().Prepare(assetCompilerContext, assetItem);
builder.Root.Add(result.BuildSteps);
builder.Run(Stride.Core.BuildEngine.Builder.Mode.Build);
var video = game.Content.Load<Video>(location);

VideoComponent component = new VideoComponent();
component.Source = video;
component.LoopVideo = true;
component.PlayAudio = true;


var entity = new Entity("Video");
entity.Add(new VideoManager());
entity.Add(component);

// ---

public class VideoManager : SyncScript
{

    public override void Update()
    {
    }

    public override void Start()
    {
            var videoComponent = Entity.Get<VideoComponent>();
            videoComponent.Instance.Play();
    }
}

My reasoning:

  1. VideoComponent requires VideoInstance
  2. VideoInstance is created from Video attached to the VideoComponent by the VideoProcessor
    1. VideoProcessor requires the VideoComponent to be present
    2. VideoInstance requires VideoComponent.Source.FileProvider to contain the DataUrl from a Video on a FileProvider -> "Video files needs to be stored on the virtual file system in a non-compressed form."
    3. Hopefully, by using STRIDE_GRAPHICS_API_DIRECT3D11 and https://github.com/stride3d/stride/blob/master/sources/engine/Stride.Video/VideoInstance.Direct3D.cs I can avoid FFMpeg requirement on the target computer.
  3. Video is created by the VideoAssetCompiler.
    1. The only way I've found to use compiler is to set up a new Builder instance alongside VideoAssetCompiler. It seems like neither are present within the Game.Services. Builder was created according to Stride's own deprecated tests.
    2. VideoAssetCompiler uses new ContentManager(MicrothreadLocalDatabases.ProviderService); which does not seem to share the space with Game.Content; so I have no access to the result with var video = game.Content.Load<Video>(location); in my code, as in - "file not found". Manual inspection of the Game.Content's does also confirm this.
      1. VideoAssetCompiler's ContentManager is hard-coded and can't be injected as a strategy.
    3. VideoAssetCompiler on windows has a hard limitation - FFMpeg must be present either in the directory of the executable; or the ../../Content; even when my system has FFMpeg in the PATH; it will not be cosidered due to ToolLocator.LocateTool if(!OperatingSystem.IsWindows()).
      1. ToolWindow behaviour is hard-coded and can't be injected as a strategy.
      2. FFMpeg as-a-converter is hard-coded and can't be injected as a strategy.
      3. ❗FFMpeg is also required even if the conversion is unnecessary
    4. With manually-copied FFMpeg I've managed to run the compilation; but even then the file is not in the same file provider.

What I am trying to achieve:

  1. Load a video file in *.bik format to play as a intro video.
  2. Video file is loaded at runtime from a user-given location.

What are my "wishes"

The best situation for me would be to stream the video from the original format, using e.g. similar approach to https://github.com/nickdu088/Bink-Unity-Player/blob/main/Assets/Scripts/BinkPlayer.cs ; reusing VideoInstance logic to modify the VideoTexture.

I can accept copying the video to the VirtualDisk, but that adds unnecessary latency if I understand it correctly.

I can also understand the need to convert to an uncompressed format, but then I should not have to rely on the VideoConverter that is intrinsically tied to the Asset's. and FFMpeg

e: So ideally,

Video video = Video.LoadStreaming(new BinkVideoStreamer(@"Path"));
VideoComponent component = new VideoComponent();
component.Source = video;

var entity = new Entity("Video");
entity.Add(new VideoManager());
entity.Add(component);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions