Tuna

Tuna v1.9.9

ikarycs

New Member
You'd have to use a browser source to implement animations.
hi, thanks for your reply.
I'm new to OBS so idk very much about it, however, my issue is not the animations, is rather how to make the text source fade out a few seconds after the song changes, the sources are always active while the music is playing and the text source only changes after it periodically checks the .txt files

EDIT: just noticed you are the maker of the plugin, TYVM btw :)
 

univrsal

Active Member
hi, thanks for your reply.
I'm new to OBS so idk very much about it, however, my issue is not the animations, is rather how to make the text source fade out a few seconds after the song changes, the sources are always active while the music is playing and the text source only changes after it periodically checks the .txt files

EDIT: just noticed you are the maker of the plugin, TYVM btw :)
Yeah what I mean is that a text source is not capable of doing that, which is why you'd need the browser source which can do this kind of stuff. I posted something like this a while ago
I made another quick html file to demonstrate the browser widget.
f-gif.72778

HTML:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Widget</title>
    </head>
    <body>
        <style>
            p {
                text-align: center;
                font-family: Arial, Helvetica, sans-serif;
                font-weight: bold;
                text-transform: uppercase;
                -webkit-animation-duration: 1s;
                animation-duration: 1s;
                -webkit-animation-fill-mode: both;
                animation-fill-mode: both;
                padding-top: 15px;
                color: white;
                filter: drop-shadow(0px 0px 4.5px black);
                font-size: 36pt;
            }

            @keyframes fadein {
                0% {
                    opacity: 0;
                    margin-top: -60px;
                }
                100% {
                    opacity: 1;
                    margin-top: 0px;
                }
            }
            @keyframes fadeout {
                0% {
                    opacity: 1;
                    margin-top: 0px;
                }
                100% {
                    opacity: 0;
                    margin-top: -60px;
                }
            }

            .fade-in {
                -webkit-animation-name: fadein;
                animation-name: fadein;
            }
            .fade-out {
                -webkit-animation-name: fadeout;
                animation-name: fadeout;
            }
        </style>
        <p id="data"></p>

        <script>
            var text = null;
            var data_element = document.getElementById("data");
            function fetch_data() {
                fetch("http://localhost:1608/")
                    .then((response) => response.json())
                    .then((data) => {
                        let new_text =
                            data["artists"][0] + " - " + data["title"];
                        if (new_text !== text) {
                            text = new_text;
                            data_element.innerText = text;
                            data_element.classList.remove("fade-out");
                            data_element.classList.add("fade-in");
                            setTimeout(() => {
                                data_element.classList.remove("fade-in");
                                data_element.classList.add("fade-out");
                            }, 8000);
                        }
                    })
                    .catch(function () {
                        // Do nothing
                    });
            }

            setInterval(fetch_data, 500);
        </script>
    </body>
</html>
 

ikarycs

New Member
Yeah what I mean is that a text source is not capable of doing that, which is why you'd need the browser source which can do this kind of stuff. I posted something like this a while ago
tyvm for taking the time to do so and to reply :)
I ended up doing what u told me, so I edited the widget (took me nearly the whole day since I'm not a pro in code), I'd like to give u some feedback regarding what I did and saw.
  1. the web-browser data hosting wont start if u have selected VLC in song souce (in basic Tab), u need to manually select web-browser and hit start, and then switch back to VLC (if u dont switch back to VLC the .json wont update any data, it will stay blank), this took me some hours to figure since I didn't know were the problem was, I even checked my firewall.
  2. adding a few lines of CSS and Script code would make this feature available for other ppl (at least for those that use the web-browser widget) that look for the same style of fading that I like, I even added a variable in witch later on I can edit the .html widget and modify the duration of the widget before it dissapear. I'll post the code of my widget for future ppl that perhaps are looking for this effect in OBS now playing overlay.
HTML:
<!DOCTYPE html>
<html>
    <style>
        body { margin: 0px; overflow: hidden;}

        .info {
            overflow: hidden;
            padding-left: 10px;
            padding-right: 10px;
        }

        .widget {
            padding: 8px;
            background-color: rgb(44, 44, 44);
            border-radius: 4px;
            border-color: rgb(22, 22, 22);
            height: 85px;
            box-shadow: 0px 0px 5px black;
            margin: 8px;
            position: relative;
            z-index: -2;
        }
        
        #invi {           
            transition: opacity 1s linear 1s;
        }
        
        #cover {
            height: 100%;
        }

        .image-box {
            box-shadow: 0 0 4px 4px rgba(0, 0, 0, .5) inset;
            border-radius: 4px;
            border-width: 1px;
            height: 100%;
            float: left;
        }
        
        .image-box img {
            position: relative;
            z-index: -1;
            border-radius: 4px;
        }

        #title {
            font-size: xx-large;
            font-weight: bold;
        }

        p {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            color: white;
            margin: 0px;
            padding-bottom: 2px;
        }
        
        #artist {
            font-size: x-large;
        }
        
    </style>

    <body>
        <div class="widget" id="invi">
            <div class="image-box">
                <img src="placeholder.png" id="cover">
            </div>
            <div class="info">
                <p id="title">Title</p>
                <p id="artist">Artist</p>
            </div>
        </div>
    </body>
    
    <script>
        var last_cover = '';
        var last_artist = '';
        var last_title = '';
        var myfader = 0;
        var myuptime = 9;

        function fetch_data() {
            fetch('http://localhost:1608/')
            .then(response => response.json())
            .then(data => {
                // data now contains the json object with song metadata

                
                // artist list
                var artists = '';
                var array = data['artists'];
                for (var i = 0; i < array.length; i++) {
                    artists += array[i];
                    if (i < array.length - 1)
                        artists += ', ';
                }

                document.getElementById('title').innerText = data['title'];
                if (data['cover_url'] !== last_cover || // Refresh only if meta data suggests that the cover changed
                    (data['title'] !== last_title &&    // When using MPD the path is always the cover path configured in tuna
                    artists !== last_artist))           // which means it won't change so we check against other data
                {
                    document.getElementById('invi').style.opacity = '1';
                    myfader = 0;
                    // Random number at the end is to prevent caching
                    document.getElementById('cover').src = data['cover_url'] + '?' + Math.random();
                    last_cover = data['cover_url'];
                }

                if (artists === data['album'] || data['album'] === undefined) // Some singles have the artist as the album, which looks strange with the other subtitle
                    document.getElementById('artist').innerText = 'by ' + artists;
                else
                    document.getElementById('artist').innerText = 'by ' + artists + ' from ' + data['album']
                
                last_artist = artists;
                last_title = data['title'];
            })
            .catch(function() {
                // Do nothing
            });
        myfader++
        if (myfader >= myuptime * 2){
        document.getElementById('invi').style.opacity = '0';
        }
        }
        
        setInterval(fetch_data, 500);
    </script>
</html>

the var "myuptime" is set to 9, that is the number in seconds the widget stays up after the song changes, I believe that if a song is shorter than that value the code might malfunction until the next longer track
 

univrsal

Active Member
tyvm for taking the time to do so and to reply :)
I ended up doing what u told me, so I edited the widget (took me nearly the whole day since I'm not a pro in code), I'd like to give u some feedback regarding what I did and saw.
  1. the web-browser data hosting wont start if u have selected VLC in song souce (in basic Tab), u need to manually select web-browser and hit start, and then switch back to VLC (if u dont switch back to VLC the .json wont update any data, it will stay blank), this took me some hours to figure since I didn't know were the problem was, I even checked my firewall.
  2. adding a few lines of CSS and Script code would make this feature available for other ppl (at least for those that use the web-browser widget) that look for the same style of fading that I like, I even added a variable in witch later on I can edit the .html widget and modify the duration of the widget before it dissapear. I'll post the code of my widget for future ppl that perhaps are looking for this effect in OBS now playing overlay.
HTML:
<!DOCTYPE html>
<html>
    <style>
        body { margin: 0px; overflow: hidden;}

        .info {
            overflow: hidden;
            padding-left: 10px;
            padding-right: 10px;
        }

        .widget {
            padding: 8px;
            background-color: rgb(44, 44, 44);
            border-radius: 4px;
            border-color: rgb(22, 22, 22);
            height: 85px;
            box-shadow: 0px 0px 5px black;
            margin: 8px;
            position: relative;
            z-index: -2;
        }
      
        #invi {         
            transition: opacity 1s linear 1s;
        }
      
        #cover {
            height: 100%;
        }

        .image-box {
            box-shadow: 0 0 4px 4px rgba(0, 0, 0, .5) inset;
            border-radius: 4px;
            border-width: 1px;
            height: 100%;
            float: left;
        }
      
        .image-box img {
            position: relative;
            z-index: -1;
            border-radius: 4px;
        }

        #title {
            font-size: xx-large;
            font-weight: bold;
        }

        p {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            color: white;
            margin: 0px;
            padding-bottom: 2px;
        }
      
        #artist {
            font-size: x-large;
        }
      
    </style>

    <body>
        <div class="widget" id="invi">
            <div class="image-box">
                <img src="placeholder.png" id="cover">
            </div>
            <div class="info">
                <p id="title">Title</p>
                <p id="artist">Artist</p>
            </div>
        </div>
    </body>
  
    <script>
        var last_cover = '';
        var last_artist = '';
        var last_title = '';
        var myfader = 0;
        var myuptime = 9;

        function fetch_data() {
            fetch('http://localhost:1608/')
            .then(response => response.json())
            .then(data => {
                // data now contains the json object with song metadata

              
                // artist list
                var artists = '';
                var array = data['artists'];
                for (var i = 0; i < array.length; i++) {
                    artists += array[i];
                    if (i < array.length - 1)
                        artists += ', ';
                }

                document.getElementById('title').innerText = data['title'];
                if (data['cover_url'] !== last_cover || // Refresh only if meta data suggests that the cover changed
                    (data['title'] !== last_title &&    // When using MPD the path is always the cover path configured in tuna
                    artists !== last_artist))           // which means it won't change so we check against other data
                {
                    document.getElementById('invi').style.opacity = '1';
                    myfader = 0;
                    // Random number at the end is to prevent caching
                    document.getElementById('cover').src = data['cover_url'] + '?' + Math.random();
                    last_cover = data['cover_url'];
                }

                if (artists === data['album'] || data['album'] === undefined) // Some singles have the artist as the album, which looks strange with the other subtitle
                    document.getElementById('artist').innerText = 'by ' + artists;
                else
                    document.getElementById('artist').innerText = 'by ' + artists + ' from ' + data['album']
              
                last_artist = artists;
                last_title = data['title'];
            })
            .catch(function() {
                // Do nothing
            });
        myfader++
        if (myfader >= myuptime * 2){
        document.getElementById('invi').style.opacity = '0';
        }
        }
      
        setInterval(fetch_data, 500);
    </script>
</html>

the var "myuptime" is set to 9, that is the number in seconds the widget stays up after the song changes, I believe that if a song is shorter than that value the code might malfunction until the next longer track
I can't reproduce your issue. Did you check this checkbox?
1637418501400.png

This will start the webserver and I didn't have to select the webbrowser source beforehand.

Since you posted the html here anyone can copy it if they want. I might add it to the plugin data as an extra example, but I haven't seen anybody really use the feature so I'm not sure if it's worth it.
 

Meat_PoPsiclez

New Member
Hi, I updated to 1.6.1 version and I cannot add any source in the VLC tab.
The scene list is outdated, I can see scenes which no longer exist, and when I pick one of my scenes with a VLC playlist in it, Tuna won't show any source.
I thought about deleting Tuna settings, but I couldn't find them.
OBS 27.1.3
I'm also experiencing what looks like the same issue.
Source field is never populated,with Tuna started or stopped, regardless of hitting refresh.
I don't see removed scenes, but rather my scene dropdown is populated with scenes AND the vlc playlists contained in them.

The work around is to move VLC sources out of groups. When they're directly in a scene and not a group, it functions as expected.
 

Moa

New Member
Hello everyone,

I have a strange issue. For some files, cover doesn't want to display (while it works perfectly fine on VLC for instance). What bugs me is taht when I remove some tags (composer, artists, album,...) the cover will appear. Is there some tags limit or something like that ? I also tried to shorten some tags, or remove special caracters but it doesn't seem to be what cause the error. I also moved the files to a different directory (with shorter absolute path) but it doesn't fix it either.

Here are the tags of a file with broken cover if you want to replicate the error (I suppose I'm not allowed to join flac even it it is royalty free music):
Filename: Résonances - RESONANCES -2021- INTER'ZICKS- - 01 EUSEBIUS ET MLHO7 - Interglitches 2021.flac
Track: 1
Title: EUSEBIUS ET MLHO7 - Interglitches 2021
Artist: Résonances
Album Artist: Résonances
Album: RESONANCES [2021: INTER'ZICKS]
Year: 2021
Comment: Visit https://resonances.bandcamp.com

What tags do you remove to fix it?

Removing Artist or Album tag seems to fix it. By the way, I don't know if it's an intended behavior, but when there is no Artist tag, it replaces the Artist with the letter "m" (as in the %m variable I guess), and same for Album tag which is raplaced by a "m".
 

MAX1DELIFE

New Member
Yesterday the app stops to work, when i try to recover the activaction token, the OBS crashes immediately. I already have trying evething that i got in mind and nothing changes, works flawlessly for almost 3 weeks but chashes everytime now. Anyone have some suggestion? Thanks anyway !!
 

univrsal

Active Member
Yesterday the app stops to work, when i try to recover the activaction token, the OBS crashes immediately. I already have trying evething that i got in mind and nothing changes, works flawlessly for almost 3 weeks but chashes everytime now. Anyone have some suggestion? Thanks anyway !!
Are you using the latest version? There was a crash a while ago, but it has been fixed.
 
Top