Determine dependencies for ffplay

The snap for Streamlink seems to function in my limited tests so far. It bundles the media player ffplay by using stage-packages to add ffmpeg. I also copied the lists from the snapcraft.yaml ffmpeg snap, to be safe.

Next step is to clean-up and isolate the minimum list of dependencies. I used the --debug --shell-after to start a command:
ldd prime/usr/bin/ffplay

Here is the output:
ldd-ffplay

Is this output from ldd the minimum required? for ffplay to function. Are the not found items optional? because ffplay seems to work when the snap is called in my Raspi.
The follow-up question, is this list still applicable across platforms? amd64 / arm64 / armhf

no, they are not … but you are using ldd on a binary outside of the context it will eventually be run when it lives in the snap …

the final snap will generate wrappers that set your LD_LIBRARY_PATH to $SNAP/usr/lib and friends.

you can check if your libs are included with something like:

find prime/ -name '*libavfilter.so.6*'

as long as they are not living in some exotic subdir (which you could then append to LD_LIBRARY_PATH via an environment: entry in snapcraft.yaml if need) the binary should just find them when running the snap.

Thanks, that makes sense.

@addq1eax I did some testing with surprising results (I was wrong before). I tried changing stage-packages and tested playing Youtube and Twitch to see what continues to works.

  1. Removed all stage-packages. ffplay is part of ffmpeg so it didn’t work but piping to player and LiveProxy worked fine. 22 MB snap.

  2. Used stage-snaps to stage ffmpeg snap and no other stage-packages. ffplay, piping to player and LiveProxy all worked. 76 MB snap.

    ...
    stage-snaps:
      - ffmpeg/latest/stable
    ...

Youtube and Twitch both worked without ffmpeg.

There are ffmpeg options listed in help streamlink --help | grep ffmpeg. In Github’s issues I saw people piping to ffmpeg and not using those options, which is where I got the idea to do the same with players. I tried these options and got no verbose output from ffmpeg, like they were just silently ignored. Stream was saved.

streamlink <URL> best --ffmpeg-video-transcode h264 --ffmpeg-audio-transcode copy --ffmpeg-verbose --output $HOME/test.mp4

I don’t know anymore if streamlink needs ffmpeg or not. Does it use ffmpeg at all or just passes streams to player?! I’m confused. :face_with_raised_eyebrow:

If it doesn’t use ffmpeg then there is no need to package it.

This is interesting info. Scanning a little, I can see that hls.py references the FFMPEGMuxer, and looking in ffmpegmux.py there is a line about commands with ffmpeg, ffmpeg.exe, and avconv.exe

So if I had to guess, Streamlink will use the executables when available. So it isn’t making calls into the ffmpeg libraries.The imports at the top of ffmpegmux.py seem to only relate to io (file system, streams). I think this is sensible if ffmpeg binary already does a lot (swiss army knife) and will be installed on the system from many other tools.

It sounds like what the snap can do is try to ship a example shell script, located at SNAP_USER_DATA which shows the stdout pipe argument to VLC that you already supplied in the other post.

Streamlink will use the executables when available

If you don’t package it in snap it will not be available. Streamlink isn’t able to see systems ffmpeg. Still it works without it.

Did some more tests with Youtube and Twitch and these commands work witout ffmpeg packaged in snap with just these plugs. I used snap install --dangerous streamlink*.snap on local builds to enforce strict confinment because --devmode ignores plugs.

streamlink <URL> <QUALITY> --stdout | vlc -
streamlink --player-external-http --player-external-http-port <PORT> <URL> <QUALITY>
streamlink <URL> <QUALITY> --output $HOME/test.mp4
...
apps:
  streamlink:
    command: bin/streamlink
    plugs:
    - home
    - network
    - network-bind
...

Maybe some streams do need ffmpeg but Youtube and Twitch don’t.

snap can do is try to ship a example shell script

What would the purpose of this script? You can show streamlink usage in snap description.

Right. I played more with the youtube-dl snap to learn from that configuration and it helps me compare. It has similar functionality.

The example script is to show the user that expects the VLC player to launch. The usage description is essential. The example script would be to demonstrate a use case like bobross.sh could be:

#!/bin/sh


# check for player argument 

for i in "$@"
do
case $i in
    -p=*|--player=*)
    PLAYER="${i#*=}"
    shift # past argument=value
    ;;
    *)
          # unknown option
    ;;
esac
done

if [ -n "${PLAYER}" ]; then
  echo "The player argument requires special handling by the snap."
  echo "Either pipe stdout, or connect to LiveProxy."
  echo "For example, to pipe to VLC, call: "
  echo "      test-streamlink <URL> 720p --stdout | vlc -"
  echo ""
  echo "To use LiveProxy for visiting Bob Ross at 720p: "
  echo "      vlc http://127.0.0.1:53422/play/?url=twitch.tv/bobross&default-stream=720p"
  echo ""
fi
test-streamlink twitch.tv/bobross 720p --config=/home/user/snap/test-streamlink/common/streamlinkrc --stdout | vlc -

Another user expectation might be the dot config (~/.streamlinkrc). I’ve been making it available at $SNAP_DATA. Now I see there is a Personal Files interface. So that could be a better way to give the user their dot config.

The example script would be to demonstrate a use case like bobross.sh could be

#!/bin/bash
#
# Due to Snap security constraints pipe output to players
streamlink twitch.tv/bobross 720p --stdout | vlc -

# Here is how you do this and that
streamlink ...

I don’t understand why you would duplicate what wrapper does in example script. Wrapper script is essential to explaining (in words not code) what is going on and I don’t think example script should do that. One way you could provide examples is adding additional entries in apps in snapcraft.yaml.

...yaml
apps:
  create-example-script:
    command: $SNAP/script-creator
    plugs:
    - home
  create-example-playlist:
    command: $SNAP/playlist-creator
    plugs:
    - home
  streamlink:
...

These become streamlink.create-example-script and streamlink.create-example-playlist in terminal and streamlink remains just streamlink.

Another user expectation might be the dot config

I don’t see configuration being important in this case. If you think something in config is important you can expose it with snap set. For example LiveProxy’s host and port are important to have to avoid conflicts but the rest of LiveProxy configuration is not.

Now I see there is a Personal Files interface. So that could be a better way to give the user their dot config.

Snaps don’t save configurations to $HOME files. They might import configurations from there on first run. You will only be granted read access (you can try asking).

I see that you tried to load plugins with streamlinkrc. Did you try using --plugin-dirs in wrapper script? It would be nice to have something like $SNAP_USER_DATA/additional_plugins automatically loaded in addition to regular plugins.

LiveProxy daemon runs as root and uses $SNAP_DATA, while streamlink runs as $USER and uses $SNAP_USER_DATA. You need to take that into account when working with config and plugins.

Also consider users that don’t know anything about streamlink, which is majority of users. What happens when they install?! What are they expecting to happen?! Target them first then advanced users.

create-example-*. Yes, I really like that approach.

My hope with the streamlinkrc and the plugins-dir setting was to give control. There was one comment on issue 3010 that wanted to load their plugin. Since I’m not familiar with side loading or other option settings, I thought I better let the user modify the streamlinkrc to their own preference.

I do agree framing the snap with the majority of users makes more sense. Right now, the issue 3010 indicates there is perhaps two users, to be realistic. I should avoid overdoing it for a advanced audience that is not there :man_facepalming: