xbmc / inputstream.ffmpegdirect

Supports streams opened by FFmpeg's libavformat or Kodi's cURL such as plain TS, HLS and DASH (non-DRM) as well as many others. There is support for Archive/Catchup services where there is a replay window and can timeshift across that span. Also provides timeshift for live streams where rewind/pause and fast-forward would not have been available.
GNU General Public License v2.0
58 stars 42 forks source link

[HELP] hls configuration for VOD with "master" playlist #237

Closed MattRCole closed 1 year ago

MattRCole commented 1 year ago

Hi! I'm trying to write an addon that uses piped's hls setup. My main goal is just to have some given quality of video stream (like pick a stream and stick with it) with its accompanying audio, and have video playback be seek-able.

Piped gives back a "master” playlist. Here are some example m3u8 files from piped with the URI's shortened.

master playlist index.m3u8

#EXTM3U
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:URI="/api/manifest/hls_playlist/long-uri/index.m3u8?host=manifest.googlevideo.com",TYPE=AUDIO,GROUP-ID="233",NAME="Default",DEFAULT=YES,AUTOSELECT=YES
#EXT-X-MEDIA:URI="/api/manifest/hls_playlist/long-uri/index.m3u8?host=manifest.googlevideo.com",TYPE=AUDIO,GROUP-ID="234",NAME="Default",DEFAULT=YES,AUTOSELECT=YES
#EXT-X-MEDIA:URI="/api/manifest/hls_timedtext_playlist/long-uri/index.m3u8?host=manifest.googlevideo.com",TYPE=SUBTITLES,GROUP-ID="vtt",LANGUAGE="en",NAME="English",DEFAULT=NO,AUTOSELECT=YES
#EXT-X-STREAM-INF:BANDWIDTH=276566,CODECS="avc1.4D4015,mp4a.40.5",RESOLUTION=426x240,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO="233",SUBTITLES="vtt",CLOSED-CAPTIONS=NONE
/api/manifest/hls_playlist/long-uri/index.m3u8?host=manifest.googlevideo.com
#EXT-X-STREAM-INF:BANDWIDTH=361061,CODECS="avc1.4D4015,mp4a.40.2",RESOLUTION=426x240,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO="234",SUBTITLES="vtt",CLOSED-CAPTIONS=NONE
/api/manifest/hls_playlist/long-uri/index.m3u8?host=manifest.googlevideo.com
#EXT-X-STREAM-INF:BANDWIDTH=692291,CODECS="avc1.4D401E,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO="234",SUBTITLES="vtt",CLOSED-CAPTIONS=NONE
/api/manifest/hls_playlist/long-uri/index.m3u8?host=manifest.googlevideo.com
... etc

shortened video index.m3u8 linked from master playlist

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:8
#EXT-X-MAP:URI="/videoplayback/id/some-id/0?is=1&file=seg.ts"
#EXTINF:3.77,
/videoplayback/id/some-id/seg.ts
#EXTINF:5.139,
/videoplayback/id/some-id/seg.ts
#EXTINF:3.403,
/videoplayback/id/some-id/seg.ts
#EXTINF:5.439,
/videoplayback/id/some-id/seg.ts
#EXTINF:7.007,
/videoplayback/id/some-id/seg.ts
#EXTINF:3.036,
/videoplayback/id/some-id/seg.ts
#EXTINF:7.007,
/videoplayback/id/some-id/seg.ts
#EXTINF:7.007,
/videoplayback/id/some-id/seg.ts
#EXTINF:4.004,
/videoplayback/id/some-id/seg.ts
#EXTINF:4.772,
/videoplayback/id/some-id/seg.ts
#EXTINF:6.173,
/videoplayback/id/some-id/seg.ts
#EXTINF:3.837,
/videoplayback/id/some-id/seg.ts

...

#EXT-X-ENDLIST

and the link to the audio index.m3u8 looks exactly the same as the video one, just with different uris

my setup

list_item = xbmcgui.ListItem(
    path="https://path-to.piped/index.m3u8"
)
list_item.setMimeType('application/x-mpegURL')
list_item.setContentLookup(False)
list_item.setProperty("inputstream", "inputstream.ffmpegdirect")
list_item.setProperty("inputstream.ffmpegdirect.is_realtime_stream", "false")
list_item.setProperty("inputstream.ffmpegdirect.manifest_type", "hls")
list_item.setProperty("inputstream.ffmpegdirect.open_mode", "ffmpeg")

xbmcplugin.setResolvedUrl(handle=_HANDLE, succeeded=True, listitem=list_item)

This setup results in the following logs in kodi:

2023-04-23 01:15:14.439 T:19688    INFO <general>: VideoPlayer::OpenFile: plugin://plugin.video.youtube/play/?video_id=9irICRnszOc
2023-04-23 01:15:14.440 T:35072    INFO <general>: Creating InputStream
2023-04-23 01:15:14.446 T:35072    INFO <general>: AddOnLog: inputstream.ffmpegdirect: inputstream.ffmpegdirect: OpenStream() - Num Props: 3
2023-04-23 01:15:14.446 T:35072    INFO <general>: AddOnLog: inputstream.ffmpegdirect: inputstream.ffmpegdirect property: inputstream.ffmpegdirect.default_programme_duration = 336
2023-04-23 01:15:14.446 T:35072    INFO <general>: AddOnLog: inputstream.ffmpegdirect: inputstream.ffmpegdirect property: inputstream.ffmpegdirect.is_realtime_stream = false
2023-04-23 01:15:14.446 T:35072    INFO <general>: AddOnLog: inputstream.ffmpegdirect: inputstream.ffmpegdirect property: inputstream.ffmpegdirect.manifest_type = hls
2023-04-23 01:15:14.446 T:35072    INFO <general>: AddOnLog: inputstream.ffmpegdirect: Stream mimetype: application/x-mpegURL
2023-04-23 01:15:14.446 T:35072    INFO <general>: AddOnLog: inputstream.ffmpegdirect: OpenWithFFmpeg - IO handled by FFmpeg's AVFormat
2023-04-23 01:15:24.725 T:19711    INFO <general>: ES: Client  from ::ffff:192.168.1.169 timed out
2023-04-23 01:15:44.529 T:35072   ERROR <general>: CVideoPlayer::OpenInputStream - error opening [plugin://plugin.video.youtube/play/?video_id=9irICRnszOc]
2023-04-23 01:15:44.529 T:35072    INFO <general>: CVideoPlayer::OnExit()
2023-04-23 01:15:44.529 T:35072    INFO <general>: ADDON: Dll Destroyed - Inputstream FFmpeg Direct
2023-04-23 01:15:44.536 T:19688    INFO <general>: CVideoPlayer::CloseFile()
2023-04-23 01:15:44.560 T:19688    INFO <general>: VideoPlayer: waiting for threads to exit
2023-04-23 01:15:44.560 T:19688    INFO <general>: VideoPlayer: finished waiting

Any help with this would be amazing.

Am I using this plugin as intended? Should I be using a different plugin? I'm new to kodi addon development, so if I'm missing some context, I apologize and would love some help with pointers.

edit: update terminology and post name to be more specific

phunkyfish commented 1 year ago

Why not copy what the existing YouTube add-on does?

MattRCole commented 1 year ago

Good question! I've looked into the youtube addon's code and they mainly deal with dash which piped doesn't (usually) have.

I could try converting between hls and dash manifests. I don't know if that's feasible or even possible, but it could be the easiest way forward.

Assuming that sticking with hls is the way to go (which again, I'm new to streaming things so it might not be), the youtube addon uses the inputstream.adaptive plugin which, when using hls, only supports multi-bitrate playlists.

I did look into using inputstream.adaptive at first, but had no luck. I don't have the logs, but I never got the segmented playlists to run.

MattRCole commented 1 year ago

I was able to get this to work by downloading all of the necessary m3u8 files, and modifying the master playlist's uris to pointing to the locally downloaded files.

Brief example:

For the example, I saved the master playlist to /tmp/my-addon/index.m3u8, before saving the file I used the m3u8 addon to modify it to only include the video playlist of the stream we want to play with its corresponding audio playlist. I also updated the uris of both of those properties to point to the locally downloaded video/audio m3u8 files.

I downloaded the audio/video m3u8 files and saved in the same directory under the names video-index.m3u8 and audio-index.m3u8 (I also updated the uris to be absolute uris)

After all of that, I went from the m3u8 files I posted earlier to these:

New /tmp/my-addon/index.m3u8 file:

#EXTM3U
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:URI="audio-index.m3u8",TYPE=AUDIO,GROUP-ID="234",NAME="Default",DEFAULT=YES,AUTOSELECT=YES
#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE,BANDWIDTH=4565100,RESOLUTION=1920x1080,FRAME-RATE=60,CODECS="avc1.64002A,mp4a.40.2",AUDIO="234"
video-index.m3u8

abbreviated example of the /tmp/my-addon/[audio|video]-index.m3u8 file with absolute uris:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:7
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:6.6,
https://pipedproxy-xxx.kavin.rocks/videoplayback/really-long-uri/seg.ts
#EXTINF:5.8,
https://pipedproxy-xxx.kavin.rocks/videoplayback/really-long-uri/seg.ts
#EXTINF:4.966666,
https://pipedproxy-xxx.kavin.rocks/videoplayback/really-long-uri/seg.ts
#EXTINF:5.166666,
https://pipedproxy-xxx.kavin.rocks/videoplayback/really-long-uri/seg.ts

then I was able to use the config I included at the beginning of this issue with one slight change:

list_item = xbmcgui.ListItem(
    path="/tmp/my-addon/index.m3u8"
)

I got the idea to download the m3u8 files after I tried to use ffplay to play the stream, passing in the url to the master playlist, and it took about 10 minutes for ffmpeg to download all of the stream playlists before it started playing the video.

I then tried downloading all of the playlist files (like I described above) and used them with ffplay and the video started in less than 10 seconds.

After seeing that, I figured something similar might be happening with the ffmpegdirect plugin.

I haven't tried this out, but maybe just changing inputstream.ffmpegdirect.open_mode to curl would solve this issue as well. I thought of this right before posting this update.

I'm closing this issue, but will update this comment with any relevant updates.