Jump to content

virtualTvExample question


Recommended Posts

Posted
1 minute ago, VicMoore said:

@Lukeand @SamESany progress on fixing the players so they will advance to the next video when the current one finishes

Vic

I gave an update above, right?

Posted

@LukeI was asking for any new news 🙂 

Vic

  • 1 month later...
VicMoore
Posted (edited)

 

@LukeI know you are busy, and I really do appreciate the time you have given me.  I have spent a great deal of time trying to figure out why the Emby server doesn't fetch the next channel in your "virtualTVexample code.  When a program is selected to play (by clicking it in the EPG) it always starts at the beginning. It's interesting that the duration timer at the bottom of the Emby client shows the correct playing time. Also, when the program ends (and again when the duration timer ends) the following error is thrown.

*** Error Report ***

Version: 4.8.3.0

Command line: C:\Users\vic\AppData\Roaming\Emby-Server\system\EmbyServer.dll -noautorunwebapp

Operating system: Microsoft Windows 10.0.22621

Framework: .NET 6.0.27

OS/Process: x64/x64

Runtime: C:/Users/vic/AppData/Roaming/Emby-Server/system/System.Private.CoreLib.dll

Processor count: 4

Data path: C:\Users\vic\AppData\Roaming\Emby-Server\programdata

Application path: C:\Users\vic\AppData\Roaming\Emby-Server\system

System.NullReferenceException: System.NullReferenceException: Object reference not set to an instance of an object.

at Emby.LiveTV.LiveTvManager.RefreshEmbyChannelsInternal(IProgress`1 progress, CancellationToken cancellationToken)

Source: Emby.LiveTV

TargetSite: Void MoveNext()

 

From my novice knowledge I assume that this error was caused by the server failing to find the next program to play.  To remedy the problem the server fetches channels again. I am sure the server is doing this because it believes it's out of channel data. 

 

2024-03-08 08:37:20.518 Info PseudoTVTuner: ======embyTv====== Ensure Channel Schedule - tuner Channel Id = 2

2024-03-08 08:37:20.518 Info PseudoTVTuner: ======embyTv====== Ensure Channel Schedule - newSchedule = False

2024-03-08 08:37:20.518 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - tuner Channel Id = 2

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - tuner = {"Id":"7e34041bfda64e9e9baa230c10822abb","Type":"pseudotvtuner","ImportFavoritesOnly":false,"PreferEpgChannelImages":true,"PreferEpgChannelNumbers":false,"AllowHWTranscoding":true,"AllowMappingByNumber":true,"ImportGuideData":true,"TunerCount":0,"ProviderOptions":"{\"UserId\":\"fb01ce97647f48a9ae4067b4c0adb172\",\"ChannelNames\":[\"Channel\",\"Channel2\",\"Channel3\"],\"ChannelNumbers\":[\"1\",\"2\",\"3\"],\"Types\":[\"TV\",\"TV\",\"TV\"],\"EpgActions\":[\"New\",\"New\",\"New\"],\"Ids\":

---- I removed data here to save space ---

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - ChannelNames = ["Channel","Channel2","Channel3"]

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - ChannelTypes = ["TV","TV","TV"]

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - ProgramIds = [["775","35368","224416","32","1032773","224417","775","35369","224403","32","1032774","224405","775","35370","224404","32","1032775","224406","775","35371","224407","32","1032776","224408","775","35372","224409","32","1032777","224410"],["1012022","1056400","1012023","1056643","1012024","1056966","1012025","1056941","1012026","1056655","1012027","1056735","1012028","1057062","1012029","1056519","1012030","1056718","1012031","1056670","1012032","1056820","1012033","1056884","1012034","1056945","1012035","1056954","1012036","1056518","1012037","1056970","1012038","1056722","1012039","1056749","1012040","1056774","1012041","1056974","1012042","1056984","1012043","1056810","1012044","1056550","1012045","1057059","1012046","1056726","1012047","1056709","1012048","1056617","1012049","1056684","1012050","1056656","1012051","1056840","1012052","1057008","1012053","1056622","1012054","1056854","1012055","1056523","1012056","1056872","1012057","1056466","1012058","1056501","1012059","1056437","1012060","1056452","1012061","1056403","1012062","1056517","1012063","1056730","1012064","1056745","1012065","1056980","1012066","1056491","1012067","1056791","1012068","1056940","1012069","1056589","1012070","1056717","1012071","1056932","1012072","1056946","1012073","1056991","1012074","1056603","1012075","1056984","1012076","1056592","1012077","1056438","1012078","1056620","1012079","1056518","1012080","1056385","1012081","1056754","1012082","1056731","1012083","1056614","1012084","1056477","1012085","1056905"],["146","1056419","150","1056641","144","1056907","157","1056715","148","1056562","155","1056395","143","1056445","160","1056661","158","1056925","151","1056693","137","1056631","153","1056589","162","1057044","159","1056987","163","1056763","164","1056720","177","1057031","165","1056781","171","1057042","173","1056854","170","1056727","161","1057035"]]

2024-03-08 08:37:20.519 Info PseudoTVTuner: ======embyTv====== Create Channel Schedule - Channel Ids = ["146","1056419","150","1056641","144","1056907","157","1056715","148","1056562","155","1056395","143","1056445","160","1056661","158","1056925","151","1056693","137","1056631","153","1056589","162","1057044","159","1056987","163","1056763","164","1056720","177","1057031","165","1056781","171","1057042","173","1056854","170","1056727","161","1057035"]

2024-03-08 08:37:20.589 Info LiveTV: Loading live tv data from C:\Users\vic\AppData\Roaming\Emby-Server\programdata\data\livetv\seriestimers

2024-03-08 08:37:20.590 Info TaskManager: Refresh Guide Completed after 0 minute(s) and 1 seconds

2024-03-08 08:37:25.265 Info App: Sqlite: 284 - automatic index on LastWatchedEpisodes(SeriesPresentationUniqueKey)

2024-03-08 08:37:25.703 Info App: Sqlite: 284 - automatic index on LastWatchedEpisodes(AlbumId)

2024-03-08 08:37:40.352 Info App: Sqlite: 284 - automatic index on LastWatchedEpisodes(SeriesPresentationUniqueKey)

2024-03-08 08:37:41.397 Info App: Sqlite: 284 - automatic index on LastWatchedEpisodes(AlbumId)

2024-03-08 08:42:37.315 Info Server: http/1.1 POST http://localhost:8096/emby/LiveTv/TunerHosts?X-Emby-Client=Emby Web&X-Emby-Device-Name=Microsoft Edge Windows&X-Emby-Device-Id=e65aab42-985c-44f6-ae8f-bd965291d929&X-Emby-Client-Version=4.8.3.0&X-Emby-Token=x_secret1_x&X-Emby-Language=en-us&reqformat=json. UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0

2024-03-08 08:42:37.319 Info TaskManager: Queueing task RefreshChannelsScheduledTask

2024-03-08 08:42:37.319 Info TaskManager: Executing Refresh Guide

2024-03-08 08:42:37.319 Info Server: http/1.1 Response 200 to ::1. Time: 5ms. POST http://localhost:8096/emby/LiveTv/TunerHosts?X-Emby-Client=Emby Web&X-Emby-Device-Name=Microsoft Edge Windows&X-Emby-Device-Id=e65aab42-985c-44f6-ae8f-bd965291d929&X-Emby-Client-Version=4.8.3.0&X-Emby-Token=x_secret1_x&X-Emby-Language=en-us&reqformat=json

2024-03-08 08:42:37.320 Error LiveTvManager: Error getting channels

*** Error Report ***

Version: 4.8.3.0

Command line: C:\Users\vic\AppData\Roaming\Emby-Server\system\EmbyServer.dll -noautorunwebapp

Operating system: Microsoft Windows 10.0.22621

Framework: .NET 6.0.27

OS/Process: x64/x64

Runtime: C:/Users/vic/AppData/Roaming/Emby-Server/system/System.Private.CoreLib.dll

Processor count: 4

Data path: C:\Users\vic\AppData\Roaming\Emby-Server\programdata

Application path: C:\Users\vic\AppData\Roaming\Emby-Server\system

System.NullReferenceException: System.NullReferenceException: Object reference not set to an instance of an object.

at Emby.LiveTV.LiveTvManager.RefreshEmbyChannelsInternal(IProgress`1 progress, CancellationToken cancellationToken)

Source: Emby.LiveTV

TargetSite: Void MoveNext()

 

@Luke Can I modify the "Ensure Channel Schedule" code in the "VirtualTvExample" so it will provide to Emby the next program to play.  For example, as a temporary fix, can I reload the channel data at the proper point to start playing the next program and then tell Emby to start playing it?  If this idea is worthless, please give me some pointers on what I can do. 

Any success I have, I will share with @pünktchenand he is always welcome to use freely any of my code in any way that he chooses.    

Vic

 

 

Edited by VicMoore
Posted
Quote

Can I modify the "Ensure Channel Schedule" code in the "VirtualTvExample" so it will provide to Emby the next program to play. 

No, this comes from the EPG. It will just start playing the channel at the current time, meaning whatever is currently on the channel.

VicMoore
Posted (edited)

@Luke I discovered this a short while earlier today.  

Is the problem in the server code? I ask this because the error log says the server was not able to find the next program to play.

Should I abandon this project?  Will a fix be available anytime soon? 

Vic

Edited by VicMoore
Posted

Where does it say that?

VicMoore
Posted (edited)

@Luke I read it in the Emby log.  I will try and recreate the event and send you the log.  I have been watching via log messages each time the server calls anything in the Tuner code trying to understand why the next channel is found OK in Chrom but not with Android. Sometimes even Edge goes to the next program OK.  As a temporary fix I was considering sending a playlist to the client when a program is requested.  I know @pünktchenhas this working.   I am only interested in this solution for my own use.  Do you have any ballpark idea when this problem will be solved?

Vic

Edited by VicMoore
  • Thanks 1
VicMoore
Posted

@LukeWhile waiting for the problems associated with playing programs in the virtualTvExample code, I decided to try a simple work around. One similar to what @pünktchenis doing. In the GetChannelStreamMediaSources task I added a small program that builds a playlist from the schedule info and then I send that playlist to the client with a "Play Now" command. I have tested this idea and it works. I have experienced one strange problem when clicking a movie to be played. The client plays the playlist OK, but it adds trailers for the movies to the front of the playlist.  TV shows are played OK.  All of the code is below. Now programs start at the proper time and programs in the schedule play sequentially.

Do you have any suggestions on how to improve this idea?  Of course, when the changes for the virtualTvCode is ready I will remove this code.

Vic

 

        protected override Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, BaseItem dbChannnel, ChannelInfo tunerChannel, CancellationToken cancellationToken)
        {
            this.Logger.Info("======embyTv=====> Get channel stream media sources");

            var tunerChannelId = this.GetTunerChannelIdFromEmbyChannelId(tuner, tunerChannel.Id);

            var options = this.GetProviderOptions<ProviderTunerOptions>(tuner);

            this.Logger.Info("======embyTv====== tuner channel Id " + tunerChannelId);

            // get the program that is currently airing
            var query = new InternalItemsQuery()
            {
                ParentIds = new[] { dbChannnel.InternalId },
                IsAiring = true,
                IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
                Limit = 1
            };

            var program = this.libraryManager.GetItemList(query).FirstOrDefault();

            if (program == null)
            {
                this.Logger.Info("======embyTv====== Program not found, query = " + query.ParentIds[0]);

                throw new ResourceNotFoundException("Program not found.");
            } else
            {
                this.Logger.Info("======embyTv====== (DbId) Program playing Id = " + program.GetProviderId("DbId"));
            };
            //-----------------------------------------------------------------------------------
            //
            // use the provider id we added to the program to locate the original library item
            //
            var programPlayingId = program.GetProviderId("DbId");
            var item = this.libraryManager.GetItemById( programPlayingId );

            //-----------------------------------------------------------------------------------
            RunPlaylistTest(tuner, options, tunerChannelId, cancellationToken);
            //-----------------------------------------------------------------------------------

            if (item == null)
            {
                this.Logger.Info("======embyTv====== Playing item = null");
                return Task.FromResult(new List<MediaSourceInfo>());
            }

            this.Logger.Info("======embyTv====== Playing item name = " + item.Name);
            this.Logger.Info("======embyTv====== Playing presentation unique key = " + item.Id);
            this.Logger.Info("======embyTv====== Playing display parent = " + item.DisplayParent);

            //-----------------------------------------------------------------------------------
            // pass null for the user and false for the other options such as path substitution.
            // this is an internal method to get media sources, which normally would not call mediaSourceManager.GetPlayackMediaSources.
            // the user and path substitution options will end up getting applied by the outer consumer of this, which is why they don't need to be passed down lower
            return this.mediaSourceManager.GetPlayackMediaSources(item, null, false, false, cancellationToken);
        }

=================================================================================================================================

This is the program I added.

 void RunPlaylistTest(TunerHostInfo tuner, ProviderTunerOptions options, string tunerChannelId, CancellationToken cancellationToken)
        {
            string sessionId = "";
            var sessionData = this.sessionManager.Sessions;
            var sessions = sessionData.GetEnumerator();
            SessionInfo session = new SessionInfo();
            this.Logger.Info("======embyTv====== While Loop ========================");

            while (sessions.MoveNext())
            {
                session = sessions.Current;
                this.Logger.Info("======embyTv====== While Loop - session.Id = " + session.Id + ", DeviceId = " + session.DeviceId + ", UserName = " + session.UserName);
                if (session.UserId == options.UserId)
                {
                    this.Logger.Info("======embyTv====== While Loop - User Found  = " + ", UserName = " + session.UserName);
                    if (sessionId == "")
                    {
                        sessionId = session.Id;
                        this.Logger.Info("======embyTv====== Current Session Id = " + sessionId);
                        this.Logger.Info("======embyTv====== Current Session Id = " + session.PlaylistLength);
                        this.Logger.Info("======embyTv====== Current Session Id = " + session.PlaylistIndex);
                        session.PlaylistLength = 0;
                        session.PlaylistIndex = 0;
                    }
                }
            };
            this.Logger.Info("======embyTv====== End While Loop ====================");


            if (sessionId != "")
            {
                ChannelSchedule schedule = this.GetSavedChannelSchedule(tuner, tunerChannelId);
                schedule.RemoveOldPrograms();
                List<ChannelScheduleItem> Programs = schedule.Programs;
                this.Logger.Info("======embyTv====== Programs = " + this.JsonSerializer.SerializeToString(Programs));

                DateTimeOffset startDate;
                List<long> idList = new List<long>();
                int i;

                for (i = 0; i < 12; i++)
                {
                    ChannelScheduleItem pro = Programs[i];
                    if (pro == null) break;

                    long id = pro.ItemId;
                    if (i == 0) {
                        startDate = pro.StartDate;
                        this.Logger.Info("======embyTv====== Start Time = " + this.JsonSerializer.SerializeToString(startDate));
                    }
                    idList.Add(id);
                };

                long[] mediaIds = idList.ToArray();

                this.Logger.Info("======embyTv====== Media Ids = " + this.JsonSerializer.SerializeToString(mediaIds));

                var nowDate = DateTimeOffset.UtcNow;
                //this.Logger.Info("======embyTv====== Time Now Utc = " + this.JsonSerializer.SerializeToString(nowDate));
                double ms = (nowDate - startDate).TotalMilliseconds;
                var ticks = (long)ms * 10000;
                //this.Logger.Info("======embyTv====== Time Delta in ms = " + this.JsonSerializer.SerializeToString(ms) + ", ticks = " + this.JsonSerializer.SerializeToString(ticks));

                //var command = new PlaystateRequest() { Command = PlaystateCommand.Stop, SeekPositionTicks = 0, ControllingUserId = options.UserId };
                //this.sessionManager.SendPlaystateCommand(sessionId, sessionId, command, cancellationToken);

                var playRequest = new PlayRequest() { PlayCommand = PlayCommand.PlayNow, ItemIds = mediaIds, StartPositionTicks = ticks, StartIndex = 0 };
                this.sessionManager.SendPlayCommand(sessionId, sessionId, playRequest, cancellationToken);

                this.Logger.Info("======embyTv====== =================================== 1");
            };
        }

 

 

 

 

 

 

 

 

 

 

 

  • 8 months later...
Posted
On 1/24/2024 at 12:01 AM, Luke said:

Anyway I'm assigning @SamESto look at it for both tizen and apple tv. It's low priority for him, but we will get to it.

@LukeIt's been almost a year, has any progress been made? By progress I mean fixing the Emby players so they will advance to the next video when the current one finishes, and the issue of starting at the current time rather than always at the beginning of a clicked video.

Vic

Posted
2 hours ago, VicMoore said:

@LukeIt's been almost a year, has any progress been made? By progress I mean fixing the Emby players so they will advance to the next video when the current one finishes, and the issue of starting at the current time rather than always at the beginning of a clicked video.

Vic

All apps should have this now except for Roku. To use on Android TV, make sure to be testing with the standard Emby android app.

If you see an issue anywhere let me know and we'll look at it. Thanks.

Posted

@Luke the android reference client (fire TV), the Emby Web Client, and my  Samsing TV Emby client all fail to start programs at the current time.  They always begin at the start of the current program in the Emby EPG. 

Vic 

Posted
Quote

I mean fixing the Emby players so they will advance to the next video

This is what I meant that they should all have. So you can confirm that?

Posted

@Lukeare you implying in the reply above that "fixing" the Emby players only included changing them so that they advance to the next video when the current one terminates? If so, the players will quickly get out of sync with their EPG.  I speak from much experience.  

As you know, I have created work arounds. I don't mind doing this, but it is not my fight. It should be easy to fix this problem.  You can do it as I have on the server or fix the players. You said this yourself.

Does this problem have a low priority because you plan to replace the current LiveTV architecture with something new? 

I am grateful for the "virtualTVexample" code that you gave me. I have learned much from it and have added to it new abilities.  It was a blessing.

Vic

Posted

It is a two part problem. I'm saying that is step one. Is that part functional? The second step is to be able to allow the channel to set the starting position in the video.

  • 2 weeks later...
pünktchen
Posted
On 12/12/2024 at 5:30 PM, Luke said:

All apps should have this now except for Roku.

Really? Also Apple TV?

Posted
43 minutes ago, pünktchen said:

Really? Also Apple TV?

It is in the code. Hasn’t really been tested.

VicMoore
Posted

@LukeI tested the Android reference client, the Samsung Android client and the Emby Web Client. Only the Web Client worked properly. The other two did not work for either playing the video at the current time or playing the next video when the current one finishes. I found it interesting that the progress timeline for all of the clients was working correctly. 

I know you are very busy, and @pünktchenand my requests are a low priority, but it has been one year. I am OK with you saying these problems will never be fixed.  I would then know what to do. Does this problem have a low priority because you plan to replace the current LiveTV architecture with something new? 

@Luke you are doing and have done a great job. None of my remarks are an attack on you.

I have been digging deep into the Emby "Live TV" architecture. I have learned so much about how you employ C# building solutions. I see your professional training. Learning is more important to me than creating a TV solution. @pünktchenis much better at that than me.

Vic

 

Posted

We’ll take a look at it. Thanks.

VicMoore
Posted (edited)

@LukeWhen you play a program from the EPG the media under the current time stamp is played and it starts that media from the beginning, rather than the current time. When this happens, you will have trouble transitioning to the next media in the EPG because in a short time the media at the current time will not be what you expect. For example, when the media completes playing, the current time has passed well into (or even past) the next item in the EPG. I observed this behavior in my testing.

An interesting point is that the progress display bar at the bottom of the Samsung android client properly identifies where the video should be playing, even though the video is playing from it's beginning. In other words, the client knows where it should be playing, its just not doing it. I suspect this problem is move common in your variety of clients than you suspect.

The point I am trying to make is that the problem does not divide into two parts as you suggested.

Vic

Edited by VicMoore
VicMoore
Posted

@LukeI would like to suggest that you fix this problem in the server rather than in the clients.  When you send the session command to start the video, you can just add to it the number of ticks to skip.  Just an idea from someone unfamiliar with the side effects, like the difficulties with transcoding, that this idea may involve. 

Vic

  • Thanks 1
pünktchen
Posted

A simple solution for the "start" problem maybe could be ContainerStartTimeTicks of MediaInfo. I've never seen any value other than 0 for this property. The plugins could set the required start offset and the requesting client then would request the stream with this value the same way it does normally for any other in progress item.

pünktchen
Posted
7 hours ago, VicMoore said:

I tested the Android reference client, the Samsung Android client and the Emby Web Client. Only the Web Client worked properly.

What is the Android reference client? The Android standard app works fine for me. The Android TV app not. But Luke already said that this app will not get needed code updates.

What is the Samsung Android client? Do you mean a smartphone? Because Samsung TV's don't have Android!

Btw. the Windows app also advances to the next program.

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...