Rafostar / clapper

Level up your video experience with a modern and user-friendly media player.
https://rafostar.github.io/clapper/
GNU General Public License v3.0
711 stars 34 forks source link

clapper: Add media caching via download to local storage #438

Closed Rafostar closed 1 month ago

Rafostar commented 2 months ago

The aim here is to stream an online video/audio while also at the same time download/cache it to disk (excluding adaptive content).

After download is complete, further playback and seeking are done using the locally cached file. This functionality uses GStreamer "downloadbuffer" element.

Player will emit a signal with a local download location after it completes, so application will know where downloaded file for media item is stored in case it wants to reuse it in the future.

It is up to application to set download dir and later manage downloaded content in it, removing files its not going to use on next application run and any incomplete downloads.

Rafostar commented 2 months ago

Example code to test (this time in Python :smile:):

#!/usr/bin/env python3

import gi
gi.require_version('Adw', '1')
gi.require_version('Clapper', '0.0')
gi.require_version('ClapperGtk', '0.0')
gi.require_version('GLib', '2.0')
gi.require_version('Gtk', '4.0')
from gi.repository import Adw, Clapper, ClapperGtk, GLib, Gtk
import shutil

Clapper.init(None)

download_dir = GLib.build_filenamev([GLib.get_user_cache_dir(), "example_download_dir", None])
print('Using ceche directory: {0}'.format(download_dir))

def on_download_complete(player, item, location):
    # Media downloaded. Data from this file is still used for current playback (including seeking).
    print('Download complete: {0} => {1}'.format(item.props.uri, location))

def on_activate(app):
    win = Gtk.ApplicationWindow(application=app, default_width=640, default_height=396)
    video = ClapperGtk.Video()
    controls = ClapperGtk.SimpleControls(fullscreenable=False)

    # Enable local storage caching and monitor it
    video.props.player.set_download_dir(download_dir)
    video.props.player.set_download_enabled(True)
    video.props.player.connect('download-complete', on_download_complete)

    # Configure playback
    video.props.player.props.queue.set_progression_mode(Clapper.QueueProgressionMode.CAROUSEL)
    video.props.player.set_autoplay(True)

    # Create and add media for playback
    item_1 = Clapper.MediaItem(uri='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4')
    item_2 = Clapper.MediaItem(uri='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4')
    video.props.player.props.queue.add_item(item_1)
    video.props.player.props.queue.add_item(item_2)

    # Assemble window
    video.add_fading_overlay(controls)
    win.set_child(video)
    win.present()

# Create a new application
app = Adw.Application(application_id='com.example.ClapperDownloadCache')
app.connect('activate', on_activate)

# Run the application
app.run(None)

# Finally app should cleanup before exit. Possibly moving data to
# another dir if it wants to use it on next run and deleting what's
# left (so any unfinished downloads will also be removed).
print('Cleanup')
shutil.rmtree(download_dir)
GST_PLUGIN_FEATURE_RANK=vah264dec:300 python3 ./test.py