Search code examples
javascriptgungundb

how to store image / video file using gundb?


I know the traditional way is to store image/video file in one place and then just save the reference index into db's table.

Now I am learning about gundb, I can store key-value json type data very easily, but since it is decentralized, if I wanna make a say chatroom app, how should I handle image storing (eg: user's avatar)?

I am also wondering if it is possible to make a movie-sharing app using gundb?


Solution

  • @Retric, great question! I'm not sure why people are downvoting you, they must be haters.

    You are right, it is better to store that image/video and reference it via GUN. For videos specifically, WebTorrent/BitTorrent has done P2P video sharing for over a decade now and at one point handled 40% of the world's internet traffic!

    However WebTorrent/BitTorrent is not very good with discovering/sharing those URIs (magnet links, etc.) but GUN is. So I'd recommend that as one option.

    For images, especially small ones like avatars/icons/profiles, I do often store them in GUN directly by Base64 encoding them (many websites around the world inline images/icons/sprites/avatars into CSS files with base64 data-URLs, except now you could use GUN for this).

    If you are interested in this, I wrote a small utility using jQuery that lets you drag&drop images into your website, and it'll auto-resize (pass options to overwrite it) and base64 encode it for you to then save to GUN:

    https://github.com/amark/gun/blob/master/lib/upload.js

    Here is a small example of how I use it:

    $('#profile').upload(function resize(e, up){
        if(e.err){ return } // handle error
        $('#profile').addClass('pulse'); // css to indicate image processing
        if(up){ return up.shrink(e, resize, 64) } // pass it `e` drag&drop/upload event, then I reuse the current function (named resize) as the callback for it, and tell it resize to 64px.
        $('#profile').removeClass('pulse'); // css indicate done processing.
        $("#profile img").attr('src', e.base64).removeClass('none'); // set photo in HTML!
        gun.user().get('who').get('face').get('small').put(e.base64); // save profile thumbnail to GUN
    });
    

    Finally, what about storing videos in GUN if you don't want to use BitTorrent?

    I would highly recommend using the HLS format to store videos in GUN, this would allow you to do decentralized realtime video streaming. It is a beautifully simple format that allows video streaming to work even from static files, because it stores the video in small chunks that can be streamed - which fits perfectly with GUN.

    There already is a JS based video-player for the HLS format:

    https://github.com/video-dev/hls.js/

    Based off the demo page, you can see an example of how the video is stored, like here on GitHub:

    https://github.com/video-dev/streams/tree/master/x36xhzz

    (if you click on the m3u8 file, you'll see it has metadata that 720p is stored in url_0 folder, which themselves have sub-files)

    Rather than storing the HLS video files on BitTorrent or a centralized server, you could store it in GUN using the same folder structure gun.get('videos').get('x36xhzz').get('url_0').get('url_496').get('193039199_mp4_h264_aac_hd_7.ts').once(function(video_chunk){ passToHLSplayer(video_chunk) }) such that it would be easy for HLS.js to integrate with GUN.

    Now you'll have P2P decentralized video streaming!!!

    And even cooler, you can combine it with GUN's lib/webrtc adapter and do this fully browser to browser!

    I hope this helped.