Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MonoGame.Framework.Content.Pipeline does not find ffmpeg/ffprobe in runtimes folder #7901

Open
ReMinoer opened this issue Aug 7, 2022 · 5 comments
Labels
Linux MacOS Setup Related to setuping a MonoGame project for the first time
Milestone

Comments

@ReMinoer
Copy link

ReMinoer commented Aug 7, 2022

Hi there!
I recently updated from MonoGame 3.7.1.189 to 3.81.303 and from .NET Framework to .NET 6 on my game project.
And it has gone very well, thank you for the good job ! :)

But I do have a small issue to report with MonoGame.Framework.Content.Pipeline. I'm using its package directly in my engine to cook my assets at runtime. (Note: because that package didn't exist in 3.7.1.189, I was using it at version 3.8.0.1375-develop until now. Not the best but it was working. ^^)

But by updating my projects to .NET 6 for MonoGame 3.81.303, my projects depending on MonoGame.Framework.Content.Pipeline now output the runtime assemblies inside the "runtimes/{platforms}/native" folder structure.
Problem is: ffmpeg and ffprobe are not next to the executable anymore and ExternalTool.Run is not able to find them, resulting in the following exception when cooking an audio file:

Microsoft.Xna.Framework.Content.Pipeline.InvalidContentException
  HResult=0x80131500
  Message=Failed to open file saut. Ensure the file is a valid audio file and is not DRM protected.
  Source=MonoGame.Framework.Content.Pipeline
  StackTrace:
   at Microsoft.Xna.Framework.Content.Pipeline.Audio.AudioContent..ctor(String audioFileName, AudioFileType audioFileType)
   at Microsoft.Xna.Framework.Content.Pipeline.WavImporter.Import(String filename, ContentImporterContext context)
   at Microsoft.Xna.Framework.Content.Pipeline.ContentImporter`1.Microsoft.Xna.Framework.Content.Pipeline.IContentImporter.Import(String filename, ContentImporterContext context)
   at MonoGame.Framework.Content.Pipeline.Builder.PipelineManager.ProcessContent(PipelineBuildEvent pipelineEvent)
   at MonoGame.Framework.Content.Pipeline.Builder.PipelineManager.BuildContent(PipelineBuildEvent pipelineEvent, PipelineBuildEvent cachedEvent, String eventFilepath)
   at MonoGame.Framework.Content.Pipeline.Builder.PipelineManager.BuildContent(String sourceFilepath, String outputFilepath, String importerName, String processorName, OpaqueDataDictionary processorParameters)
   at Glyph.Pipeline.RawContentLibrary.<>c__DisplayClass24_1.<CookAsset>b__0() in D:\Remi\Git\Papyrus\External\Calame\External\Glyph\Glyph.Pipeline\RawContentLibrary.cs:line 144
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)

  This exception was originally thrown at this call stack:
    Microsoft.Xna.Framework.Content.Pipeline.ExternalTool.Run(string, string, out string, out string, string)
    Microsoft.Xna.Framework.Content.Pipeline.Audio.DefaultAudioProfile.ProbeFormat(string, out Microsoft.Xna.Framework.Content.Pipeline.Audio.AudioFileType, out Microsoft.Xna.Framework.Content.Pipeline.Audio.AudioFormat, out System.TimeSpan, out int, out int)
    Microsoft.Xna.Framework.Content.Pipeline.Audio.AudioContent.AudioContent(string, Microsoft.Xna.Framework.Content.Pipeline.Audio.AudioFileType)

Inner Exception 1:
Exception: Couldn't locate external tool 'ffprobe'.

The workaround is pretty simple: you can set your PATH with a folder containing ffmpeg & ffprobe and it will work. But it's kinda sad that it doesn't find them by default since there are provided by the package.

Note that it doesn't seems to be an issue for packed/published executables (like mgcb CLI) since the package runtimes will be output next to the executable in that case.

Any insight on the subject ?
Would it be possible to make ExternalTool.Run look for executables in the valid target platforms "runtimes" folders (if existing) ?
(It is already looking for "linux" and "osx" folders to resolve ffmpeg & ffprobe.)

EDIT: I have found ways to make the package work (see following comment).

What version of MonoGame does the bug occur on:

  • MonoGame 3.8.1

What operating system are you using:

  • Windows / Linux

What MonoGame platform are you using:

  • WindowsDX / DesktopGL
@ReMinoer
Copy link
Author

I ended being able to use MonoGame.Framework.Content.Pipeline package without computer setup with a bit of configuration on my projects:

  1. As implied by MonoGame.Content.Builder.Editor csproj files, it seems mandatory to provide a <RuntimeIdentifier> in your executables csproj files depending on MonoGame.Framework.Content.Pipeline (directly or indirectly), among the ones supported by the package (win-x64, linux-x64 & osx), to output correctly the runtime dependencies:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <RuntimeIdentifier>win-x64</RuntimeIdentifier>
      </PropertyGroup>
      ...
    </Project>

    This allow your project to directly output platform-specific binaries at build and so to copy the corresponding package runtime DLLs next to the executable, including ffmpeg/ffprobe.

    That say, you will not have that behaviour if you provide multiple RuntimeIdentifiers, at least not in Visual Studio, since it will require to specify the wanted runtime identifier in the build command line. So in a Visual Studio environment, the best seems to have one project by platform if you are using MonoGame.Framework.Content.Pipeline, so each of them can have a unique RuntimeIdentifier.

    Being forced to have platform-specific executable projects when using using MonoGame.Framework.Content.Pipeline seems acceptable but the RuntimeIdentifier property remains kinda obscure and nothing except the csproj files of MonoGame.Content.Builder.Editor hint to it.

    As I said in my initial post, maybe some code to resolve the runtime assemblies from inside the output runtimes/ folder would be ideal to make the MonoGame.Framework.Content.Pipeline package work without indicate a RuntimeIdentifier in executable csproj files.

  2. I also encountered issues with mgfxc dependencies. MonoGame.Framework.Content.Pipeline package is including those dependencies as content & contentFiles but the problem is that they are not configured to be copied to dependent projects output.

    To do that, the property PackageCopyToOutput might be lacking on the Content item at line 277 of MonoGame.Framework.Content.Pipeline.csproj:

    <ItemGroup>
      <Content Include="..\Artifacts\MonoGame.Effect.Compiler\$(Configuration)\*" Exclude="..\Artifacts\MonoGame.Effect.Compiler\$(Configuration)\*.nupkg" Visible="false">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        <PackageCopyToOutput>true</PackageCopyToOutput>
      </Content>
    </ItemGroup>

    As a workaround, I ended having to include those files as content of my own directly dependent project, using GeneratePathProperty="true" and $(PkgMonoGame_Framework_Content_Pipeline) to find them:

    <Project Sdk="Microsoft.NET.Sdk">
      <ItemGroup>
        <PackageReference Include="MonoGame.Framework.Content.Pipeline" Version="3.8.1.303" GeneratePathProperty="true" />
        ....
      </ItemGroup>
      <ItemGroup>
        <Content Include="$(PkgMonoGame_Framework_Content_Pipeline)\content\*">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </Content>
      </ItemGroup>
      ...
    </Project>

For the moment, I'm good with my workaround since everything is done in my .csproj files.
That say, do you have any feedback about those two issues and the suggested solutions ?

Thanks.

@damian-666

This comment was marked as off-topic.

@damian-666

This comment was marked as off-topic.

@ReMinoer
Copy link
Author

@damian-666 Thanks for your feedbacks but it's indeed a bit off-topic. I opened that issue to talk about the MonoGame.Framework.Content.Pipeline package specifically. You should consider talking about your issues on MonoGame forum or opening other issues so it's not confusing. :)

Here is a TLDR of my original messages on MonoGame.Framework.Content.Pipeline:


Runtimes and content files of package MonoGame.Framework.Content.Pipeline are not found by default when referencing the package so parts of the pipeline are not working. It requires additional setup at the time and there are small info about it.

  • Runtimes (like ffmpeg) are not found by default when output in their default runtimes/ folder.
    • Fix: improve ExternalTool.Run so it can found platform-specific runtimes from the default runtimes/ folder.
    • Workaround: create platform-specifc executable .csproj files using an unique RuntimeIdentifier, allowing runtimes to be directly output next to the executable.
  • Content files (like mgfxc) are not output to the executable folder.
    • Fix: use property PackageCopyToOutput="true" on the Content item at line 277 of MonoGame.Framework.Content.Pipeline.csproj.
    • Workaround: it's possible to manually include them in your .csproj files referencing the package using GeneratePathProperty="true" and $(PkgMonoGame_Framework_Content_Pipeline).

(see my previous messages for details)

The two issues have both workaround so I can do with them but I hope it will possible to fix that in next versions.

@mrhelmut mrhelmut added this to the 3.8.2 milestone Sep 18, 2022
@mrhelmut mrhelmut added Linux MacOS Setup Related to setuping a MonoGame project for the first time labels Jan 19, 2024
@mrhelmut
Copy link
Contributor

Please refer to #8124 while this issue is being worked on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Linux MacOS Setup Related to setuping a MonoGame project for the first time
Projects
None yet
Development

No branches or pull requests

3 participants