Jump to content

Something kind of cool with new Prime interface


chef

Recommended Posts

chef

In this video (at about 22 seconds in) while showcasing the new amazon prime interface a cool trick happens.

The folder image (while highlighted) expands to a thumb image, and about a second later the trailer starts to play. 

That is a cool trick.

Possible maybe with some JavaScript and css in the web app? Maybe.

 

Edited by chef
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

chef

I thought I'd give this a go, to see how it could be done.

Some initial ideas.

 Embedding an iframe linking to the trailer  (like the button does on the detail page).

Easiest way to do this seems to be,  to embed the iframe into the cardOverlay.

Then resize the virtualCardScroller on hover.

That works okay.... 😆

But, there seems to be some difficulty in transitioning the cards to the right of the newly embedded video. 

Because each card in the virtual scroller is calculated specifically using a translate function in css, each card position along the x axis (in the row) would have to be recalculated on hover. 

Hmmm.... That is quite a bit of code.

I also thought about creating a 'before' pseudo element  on the card. But, I think appending the iframe to the cardOverlay is easiest.

 

Link to comment
Share on other sites

chef

Applying the iframe to the overlay container is not correct.

Seems like the first step is to create an insection observer on the webapp home page to know when elements have populated in the Dom. Only on the home page, so as to not change cards in any of the library pages.

Next, a mutation observer could possibly be used to handle card hovers, and appending the iframes, and expanding the cards when the overlays have focus.

However, because of the translation methods on the cards are handled in a dashboard library,  a separate method would have to handle adjusting the placement of each consecutive card in the virtual scroller, overriding how emby is re-drawing them in the layout.

It also creates some spacing issues when scrolling left and right. 

Might be too much to hack together.

Link to comment
Share on other sites

chef

Found some interesting ways to handle this.

First some custom CSS

div.sections.homeSectionsContainer > div > div > div > div > div.card:not(.bannerCard):hover {
width: 18.8%; 
max-height: 84%; 
position: absolute; 
z-index: 2;
transition: all 1s;
}

 

This allows the card image to grow into 16:9.

 

Next, some javascript to handle appending the iframe. Easy-peasy...

(function (win) {
    var listeners = [],
        doc = win.document,
        MutationObserver = win.MutationObserver || win.WebKitMutationObserver,
        observer;

    function ready(selector, fn) {
        // Store the selector and callback to be monitored
        listeners.push({
            selector: selector,
            fn: fn
        });
        if (!observer) {
            // Watch for changes in the document
            observer = new MutationObserver(function (mutations) {

                check();
            });
            observer.observe(doc.documentElement, {
                childList: true,
                subtree: true,
                attributes: true,
                attributeOldValue: true
            });
        }
        // Check if the element is currently in the DOM
        check();
    }

    function check(){
        for (var i = 0, len = listeners.length, listener, elements; i < len; i++) {
            listener = listeners[i];
            // Query for elements matching the specified selector
            elements = doc.querySelectorAll(listener.selector);
            for (var j = 0, jLen = elements.length, element; j < jLen; j++) {
                element = elements[j];
    
                // Make sure the callback isn't invoked with the 
                // same element more than once
                if (!element.ready) {
                    element.ready = true;
                    // Invoke the callback with the element
                    listener.fn.call(element, element);
                }
            }
        }
    }

    // Expose `ready`
    win.ready = ready;

})(this);
//div.sections.homeSectionsContainer > div > div > div > div > div.card
ready('.homeSectionsContainer', (element) => {
    ready('.virtualScrollItem ', (item) => {
        var cards = element.querySelectorAll('.card:not(.bannerCard)');
        cards.forEach(function (card) {
            card.addEventListener('onmouseenter', function (e) {
                var target = e.target;
                //Our card we just hovered on
                //We can easily append the iframe here.
                //However, where do we get the trailer URL from?            
            })
    
        });
    })
   
});

 

Still some question that needs to be answered.

1. Where do we get the trailer URL from... provider data? Does Emby have an endpoint for trailers?

2. How to force the posters on the right of the currently hovered item out of the way.

3. Lastly,  the 'cardOverlay' must remian accessible How  to make the iframe ignore mouseevents.

 

Pretty close to doing this.

Edited by chef
Link to comment
Share on other sites

GrimReaper
14 minutes ago, chef said:

1. Where do we get the trailer URL from...

Could you write a code for local trailers? My collection has like 4,000 of them. 🙄

  • Like 1
Link to comment
Share on other sites

chef

Okay! I have done it! 😆

It is a proof of concept, but this is how it is done if you were going to implement it into the WebApp.

The video is terrible because I'm not a video production guy. 

 

 

Still need to figure out how to get trailer URLs from youtube. But... I like @GrimReaper idea of trying local trailers.

 

  1. Custom Css:

Placed into Emby's custom CSS settings, this will grow the folder image into a 16:9 element to prepare for the trailer video.

div.sections.homeSectionsContainer > div > div > div > div > div.card:not(.bannerCard):hover {
width: 18.8%; 
max-height: 84%; 
position: absolute; 
z-index: 2;
transition: all 1s;
}

2. Javascript file:

This creates a mutation observer on the WebApp's Home Page that watches for the cursor entering a '.card' element, and then appending an iFrame overtop the poster image.

Once the mouse enters the card, and the custom CSS begins it's transformation into a 16:9 viewport, this javascript appends the iframe into the element.

After the mouse leaves the element, the same mutation observer removes the iframe from the DOM which resolves it back to the folder image.

(function (win) {
    var listeners = [],
        doc = win.document,
        MutationObserver = win.MutationObserver || win.WebKitMutationObserver,
        observer;

    function ready(selector, fn) {
        // Store the selector and callback to be monitored
        listeners.push({
            selector: selector,
            fn: fn
        });
        if (!observer) {
            // Watch for changes in the document
            observer = new MutationObserver(function (mutations) {

                check();
            });
            observer.observe(doc.documentElement, {
                childList: true,
                subtree: true,
                attributes: true,
                attributeOldValue: true
            });
        }
        // Check if the element is currently in the DOM
        check();
    }

    function check(){
        for (var i = 0, len = listeners.length, listener, elements; i < len; i++) {
            listener = listeners[i];
            // Query for elements matching the specified selector
            elements = doc.querySelectorAll(listener.selector);
            for (var j = 0, jLen = elements.length, element; j < jLen; j++) {
                element = elements[j];
    
                // Make sure the callback isn't invoked with the 
                // same element more than once
                if (!element.ready) {
                    element.ready = true;
                    // Invoke the callback with the element
                    listener.fn.call(element, element);
                }
            }
        }
    }

    // Expose `ready`
    win.ready = ready;

})(this);
//div.sections.homeSectionsContainer > div > div > div > div > div.card
ready('.homeSectionsContainer', (element) => {
    ready('.virtualScrollItem ', (item) => {
        var cards = element.querySelectorAll('.card:not(.bannerCard)');
        cards.forEach(function (card) {
            card.addEventListener('mouseenter', function (e) {
                var target = e.target;
                if(!target.querySelector('iframe')){
                    target.innerHTML += '<iframe style="position:absolute; top:0; left:0; width:100%; height:100%" id="player" frameborder="0" allowfullscreen="1" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" title="DUAL - Official Trailer" width="' + target.offsetWidth + '" height="' + target.offsetHeight + '" src="https://www.youtube.com/embed/uPzyA1gMNsM?//controls=0&amp;enablejsapi=1&amp;modestbranding=1&amp;rel=0&amp;showinfo=0&amp;fs=0&amp;playsinline=1&amp;origin=http%3A%2F%2Flocalhost%3A8096&amp;widgetid=2"></iframe>'
                }
                      
            })
            card.addEventListener('mouseleave', function (e) {
                var target = e.target;
                if(target.querySelector('iframe')){
                    target.removeChild(target.querySelector('iframe'));
                }
            })
    
        });
    })
   
});

 

Edited by chef
  • Like 1
Link to comment
Share on other sites

chef

While it's a cool idea, the best would be if the normal cardOverlay was present, and the trailer auto played behind it.

Also, it would be better if it wasn't a hack job 😆

 

Link to comment
Share on other sites

1 minute ago, chef said:

the best would be if the normal cardOverlay was present, and the trailer auto played behind it.

That's just theme videos with the trailer as the theme.  Certainly do-able.

This particular technique is an attempt to engage you in order to "sell" you on watching the content.  That's why the streaming providers do it.  The longer they can keep you engaged the better and more moving parts that might grab your attention increase that potential engagement.

In a personal media server, however, I feel these gimmicks are just that - mildly interesting the first time you see them building to really annoying as time goes on.  But, if enough users really want this type of thing, we could certainly do it.

  • Agree 1
  • Thanks 1
Link to comment
Share on other sites

GrimReaper
20 minutes ago, ebr said:

In a personal media server, however, I feel these gimmicks are just that - mildly interesting the first time you see them building to really annoying as time goes on.  But, if enough users really want this type of thing, we could certainly do it.

Just as theme music and theme videos, it could be made an option - it certainly wouldn't detract from Emby's appeal. 

Link to comment
Share on other sites

chef

I agree, there is definitely ulterior motives to the streaming services doing this. 

I'm many ways it could slow down the user experience in the UI. The usefulness of this is somewhat debatable.

 

 

As an aside, I found that settings pointer events to none on the iframe, allowed the video to auto-play., and repositioning the cardOverlay seemed create the desired outcome.

There is some kind of magic happening in Emby's WebApp. 😆 

It has to do with the focus frame on  poster items.

When using the keyboard to maneuver the UI, the current focus-able item gets a frame (in my case white).

However, I'm not seeing the selected element change in the dev tools when it is focused in the frame. See magic. LOL!

I believe it is using shadows instead of borders to create the frame... if so cool trick, I like it.

But, how does emby know the item has focus? 

Perhaps there is some kind of intersection/mutation observer happening in the background? Or I'm blind 😆 which is a possibility.

 

 

Link to comment
Share on other sites

46 minutes ago, GrimReaper said:

it could be made an option

It could if there is sufficient demand.  However, any feature we put behind an option that is defaulted "off" (which this certainly would be) makes the cost/benefit equation very difficult because probably < 10% of users will ever use it.  The reality is that people don't go looking for options and rarely turn them on unless they just happen to stumble on them (and many times turn them on not knowing what they are, then forget about it and wonder why the system is behaving the way it is).  That means a lot of work for very little payback.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

visproduction

Nice work!

When you do target.InnerHTML iFrame update and the mouseover is a media card on the right side of the screen, what happens? 

Does the enlarged video player div push scroll the row to the right so you can see the entire player width or does it go off the right edge of the screen?  Do you need a listener to reposition the row for this situation?  Maybe it works automatically, but probably not.  

Also, how much of this breaks with smaller browser screen widths?  I know that mobile previews have a lot of issues.  Some are fixed to work with the standard unchanged theme, but my custom css needs mobile style adjustments that I have not yet tweaked.  Do you even want to bother making it work for mobile?  You should probably, at least, see what happens with your custom work for mobile portrait and landscape.

Since you are in control of the video size, why not make it a little larger than exactly 3 card widths and make it position obviously on top and overlapping other cards.  Then the user will know that this is an extra overlay effect.  Otherwise, they could think the two card that are hidden are no longer a choice in the row after the trailer finishes.  It's a minor issue, but I think it's more user friendly to make it obvious that the player is a layer on top.

Auto dimming of the surrounding media cards?

Option to go full screen.  I don't think youtube has a visible full screen button option for embedded videos.  You might be able to add a div button that might work.  I think it's complex and maybe not worth it.

 

  • Thanks 1
Link to comment
Share on other sites

chef
8 minutes ago, visproduction said:

Nice work!

When you do target.InnerHTML iFrame update and the mouseover is a media card on the right side of the screen, what happens? 

Does the enlarged video player div push scroll the row to the right so you can see the entire player width or does it go off the right edge of the screen?  Do you need a listener to reposition the row for this situation?  Maybe it works automatically, but probably not.  

Also, how much of this breaks with smaller browser screen widths?  I know that mobile previews have a lot of issues.  Some are fixed to work with the standard unchanged theme, but my custom css needs mobile style adjustments that I have not yet tweaked.  Do you even want to bother making it work for mobile?  You should probably, at least, see what happens with your custom work for mobile portrait and landscape.

Since you are in control of the video size, why not make it a little larger than exactly 3 card widths and make it position obviously on top and overlapping other cards.  Then the user will know that this is an extra overlay effect.  Otherwise, they could think the two card that are hidden are no longer a choice in the row after the trailer finishes.  It's a minor issue, but I think it's more user friendly to make it obvious that the player is a layer on top.

Auto dimming of the surrounding media cards?

Option to go full screen.  I don't think youtube has a visible full screen button option for embedded videos.  You might be able to add a div button that might work.  I think it's complex and maybe not worth it.

 

Cool, thanks! 

Pushing the other cards over was definitely something that needed to happen. The way it worked out, the iframe becomes position absolute, and therefore grows over the other children in the row 😬. Yikes, probably not best.

I think that because the element grows in an absolute position, it would be okay on smaller browsers. But I didn't try it.

 

When I think about it, it is likely possible to have the full screen button appear on the cardOverlay.

Once pointer events were removed from the iframe inorder to auto play the video, and the cardOverlay was given a higher z-index, it became visible. So it could be possible to add Fullscreen controls to it.

That would be cool.

 

While reading through some of embys UI changes in the dev console, I can see that there has been quite a bit of media queries added to help control the flow between screen sizes.

That custom css used a percent value to try and fit the video over three cards... 😬 It could be done better 😆 like following the query sizes and whatnot. 

 

Oh, auto dimming! That's great. Should absolutely try that just to see if it is possible. Seems like something that could be done with css only.

Something like... *:not(iframe) 

Link to comment
Share on other sites

visproduction

This kind of custom update is challenging, but fun. 

Did you try to click a media card all the way on the right of the row.  What happens?  Does the row scroll to allow the expanded iframe to fit on the screen?

It's worth thinking about the user experience.  In this case the user interacts and chooses to play a trailer or not, per content.  If they like the media poster, they can hover and click to play a trailer. They are basing the choice only on the media poster.  Maybe they recognize the movie name or see an actor / actress they like in the poster image.  Maybe the rating, if they are showing, are very high, so they can want to see a trailer.  That's it.  There is no other info to review with your click on the poster scroll.

The current user experience is to open the media card, see more info about the story. See ratings, genres, actors by name and portrait.  They can also see if the media is included in any collection, the length of the content and then they can click trailer, if they want.  This is one click difference.

I would tend to prefer the current setup that gives the user much more info before they decide to watch a trailer.  That's just me.

===

A related user experience that is online is the either automatically or the admin chooses a collection of trailers or related content to present one after another to the user to get them interested in watching something, or in many social media sites to just watch, so they can send you ads.  We can already do this with a playlist of trailers.  The question then becomes how do you suggest this playlist. An example online would be imdb.com, that has a built in player that cycles through a series of videos. 

How to show this playlist? Add a clickable button to the main index page upper header area with some graphic + text that tells the user it's a collection of current featured movie trailers.  user clicks and the admin's playlist starts.  This can work, but there is no obvious way to move from trailer to start playing the actual full content, because you have to actually make a collection of the trailers in a trailer library.  The user is inside the trailer playback media.

I just thought of another option.  You can create a playlist of trailers you would like to highlight and embed this at the top of the index page, perhaps with an optional click here to see featured trailers.  This allows trailers to be played in the site, without going to the trouble of collecting them into their own library.  As the admin, you can update this playlist in Youtube as often as you want.  See: https://smashballoon.com/how-to-embed-youtube-playlist-in-wordpress/

Anyway, this is my random brainstorming.  User experience is rather important to consider.

Edited by visproduction
  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...