diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
index 5b80c452a3b..db5bb6f06eb 100644
--- a/mythtv/libs/libmythtv/mythplayer.cpp
+++ b/mythtv/libs/libmythtv/mythplayer.cpp
@@ -223,6 +223,8 @@ MythPlayer::MythPlayer(PlayerFlags flags)
       rtcbase(0),
       maxtcval(0), maxtcframes(0),
       numdroppedframes(0),
+      prior_audiotimecode(0),
+      prior_videotimecode(0),
       // LiveTVChain stuff
       m_tv(nullptr),                isDummy(false),
       // Counter for buffering messages
@@ -415,6 +417,8 @@ bool MythPlayer::Play(float speed, bool normal, bool unpauseaudio)
         return false;
     }
     rtcbase = 0;
+    prior_audiotimecode = 0;
+    prior_videotimecode = 0;
     SetEof(kEofStateNone);
     UnpauseBuffer();
     UnpauseDecoder();
@@ -1806,6 +1810,8 @@ void MythPlayer::ResetAVSync(void)
     prevtc = 0;
     avsync_next = avsync_interval;      // Frames till next sync check
     rtcbase = 0;
+    prior_audiotimecode = 0;
+    prior_videotimecode = 0;
     LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC + "A/V sync reset");
 }
 
@@ -1822,6 +1828,8 @@ void MythPlayer::InitAVSync(void)
     // Number of frames over which to average time divergence
     avsync_averaging=4;
     rtcbase = 0;
+    prior_audiotimecode = 0;
+    prior_videotimecode = 0;
 
     // Special averaging default of 60 for OpenMAX passthru
     QString device = gCoreContext->GetSetting("AudioOutputDevice","");
@@ -2170,7 +2178,7 @@ void wait_for_time(int64_t framedue)
         QThread::usleep(delay);
 }
 
-#define AVSYNC_MAX_LATE 1000000
+#define AVSYNC_MAX_LATE 10000000
 void MythPlayer::AVSync2(VideoFrame *buffer)
 {
     if (videoOutput->IsErrored())
@@ -2180,7 +2188,6 @@ void MythPlayer::AVSync2(VideoFrame *buffer)
         SetErrored(tr("Failed to initialize A/V Sync"));
         return;
     }
-    int64_t audiotimecode = audio.GetAudioTime();
     int64_t videotimecode = 0;
 
     bool dropframe = false;
@@ -2191,10 +2198,10 @@ void MythPlayer::AVSync2(VideoFrame *buffer)
     int64_t unow = 0;
     int64_t lateness = 0;
     int64_t playspeed1000 = (float)1000 / play_speed;
+    bool reset = false;
 
     while (framedue == 0)
     {
-        bool reset = false;
         if (buffer)
         {
             videotimecode = buffer->timecode & 0x0000ffffffffffff;
@@ -2210,7 +2217,7 @@ void MythPlayer::AVSync2(VideoFrame *buffer)
         {
             // cater for DVB radio
             if (videotimecode == 0)
-                videotimecode = audiotimecode;
+                videotimecode = audio.GetAudioTime();;
             // On first frame we get nothing, so exit out.
             if (videotimecode == 0)
                 return;
@@ -2244,19 +2251,31 @@ void MythPlayer::AVSync2(VideoFrame *buffer)
         if (lateness > 30000)
             dropframe = !FlagIsSet(kMusicChoice) && numdroppedframes < 10;
 
-        if (lateness <= 30000 && audiotimecode > 0 && normal_speed && !FlagIsSet(kMusicChoice))
+        if (lateness <= 30000 && prior_audiotimecode > 0
+            && prior_videotimecode > 0 && normal_speed && !FlagIsSet(kMusicChoice))
         {
             // Get video in sync with audio
-            audio_adjustment = audiotimecode - videotimecode;
-            int sign = audio_adjustment < 0 ? -1 : 1;
-            if (audio_adjustment * sign > 40)
+            audio_adjustment = prior_audiotimecode - prior_videotimecode;
+            // If there is excess audio - throw it away.
+            if (audio_adjustment < -200)
             {
-                // adjust by AVSyncIncrementMS milliseconds at a time (range 1-40)
-                rtcbase -= (int64_t)1000000 * avsync2adjustms * sign / playspeed1000;
+                audio.Reset();
+                audio_adjustment = 0;
+            }
+            int sign = audio_adjustment < 0 ? -1 : 1;
+            int64_t fix_amount = audio_adjustment * sign;
+            if (fix_amount > avsync2adjustms)
+                fix_amount = avsync2adjustms;
+            // Faster catch-up when off by more than 200 ms
+            if (audio_adjustment * sign > 200)
+                // fix the sync within 15 - 20 frames
+                fix_amount = audio_adjustment * sign / 15;
+            int64_t speedup1000 = (float)1000 * play_speed;
+            rtcbase -= (int64_t)1000000 * fix_amount * sign / speedup1000;
+            if (audio_adjustment * sign > 20 || (framesPlayed % 400 == 0))
                 LOG(VB_PLAYBACK, LOG_INFO, LOC +
                     QString("AV Sync, audio ahead by %1 ms").arg(audio_adjustment));
-            }
-            if (audio_adjustment > 1000)
+            if (audio_adjustment > 200)
                 pause_audio = true;
         }
         // sanity check - reset rtcbase if time codes have gone crazy.
@@ -2277,7 +2296,7 @@ void MythPlayer::AVSync2(VideoFrame *buffer)
             reset = true;
         }
     }
-
+    prior_videotimecode = videotimecode;
     disp_timecode = videotimecode;
 
     output_jmeter && output_jmeter->RecordCycleTime();
@@ -2307,17 +2326,6 @@ void MythPlayer::AVSync2(VideoFrame *buffer)
         audio.Pause(true);
     }
 
-    LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
-        QString("A/V timecodes audio=%1 video=%2 frameinterval=%3 "
-                "audioadj=%4 tcoffset=%5 unow=%6 udue=%7")
-            .arg(audiotimecode)
-            .arg(videotimecode)
-            .arg(frame_interval)
-            .arg(audio_adjustment)
-            .arg(tc_wrap[TC_AUDIO])
-            .arg(unow)
-            .arg(framedue)
-                );
 
     if (dropframe)
         numdroppedframes++;
@@ -2338,6 +2346,8 @@ void MythPlayer::AVSync2(VideoFrame *buffer)
         // the primary PBP will become out of sync
         if (!player_ctx->IsPBP() || player_ctx->IsPrimaryPBP())
             wait_for_time(framedue);
+        // get time codes for calculating difference next time
+        prior_audiotimecode = audio.GetAudioTime();
         videoOutput->Show(ps);
         if (videoOutput->IsErrored())
         {
@@ -2373,6 +2383,19 @@ void MythPlayer::AVSync2(VideoFrame *buffer)
     }
     else
         wait_for_time(framedue);
+
+    LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO, LOC +
+        QString("A/V timecodes audio=%1 video=%2 frameinterval=%3 "
+                "audioadj=%4 tcoffset=%5 unow=%6 udue=%7")
+            .arg(prior_audiotimecode)
+            .arg(prior_videotimecode)
+            .arg(frame_interval)
+            .arg(audio_adjustment)
+            .arg(tc_wrap[TC_AUDIO])
+            .arg(unow)
+            .arg(framedue)
+                );
+
 }
 
 void MythPlayer::RefreshPauseFrame(void)
@@ -2451,7 +2474,6 @@ bool MythPlayer::PrebufferEnoughFrames(int min_buffers)
     if (!videoOutput)
         return false;
 
-    bool paused_now = false;
     if (!(min_buffers ? (videoOutput->ValidVideoFrames() >= min_buffers) :
                         (GetEof() != kEofStateNone) ||
                         (videoOutput->hasHWAcceleration() ?
@@ -2467,19 +2489,20 @@ bool MythPlayer::PrebufferEnoughFrames(int min_buffers)
         // for the jerking is detected.
 
         bool watchingTV = IsWatchingInprogress();
-        if (!paused_now && (livetv || watchingTV) && !FlagIsSet(kMusicChoice))
+        if ( (livetv || watchingTV) && !FlagIsSet(kMusicChoice))
         {
             uint64_t frameCount = GetCurrentFrameCount();
             uint64_t framesLeft = frameCount - framesPlayed;
             uint64_t margin = (uint64_t) (video_frame_rate * 3);
             if (framesLeft < margin)
             {
-                LOG(VB_PLAYBACK, LOG_NOTICE, LOC +
-                    QString("Pause to allow live tv catch up. Position in sec. Current: %2, Total: %3")
-                    .arg(framesPlayed).arg(frameCount));
+                if (rtcbase)
+                    LOG(VB_PLAYBACK, LOG_NOTICE, LOC +
+                        QString("Pause to allow live tv catch up. Position in sec. Current: %2, Total: %3")
+                        .arg(framesPlayed).arg(frameCount));
                 audio.Pause(true);
                 avsync_audiopaused = true;
-                paused_now = true;
+                rtcbase = 0;
             }
         }
         usleep(frame_interval >> 3);
diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
index 7358d617a9d..4b295af28fe 100644
--- a/mythtv/libs/libmythtv/mythplayer.h
+++ b/mythtv/libs/libmythtv/mythplayer.h
@@ -856,6 +856,8 @@ class MTV_PUBLIC MythPlayer
     int       maxtcframes;    // number of frames seen since max to date tc
     int64_t   avsync2adjustms; // number of milliseconds to adjust for av sync errors
     int       numdroppedframes; // number of consecutive dropped frames.
+    int64_t   prior_audiotimecode;    // time code from prior frame
+    int64_t   prior_videotimecode;    // time code from prior frame
 
     // LiveTV
     TV *m_tv;
diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
index ea0aa806d59..0ad00a335ba 100644
--- a/mythtv/libs/libmythtv/tv_play.cpp
+++ b/mythtv/libs/libmythtv/tv_play.cpp
@@ -409,6 +409,7 @@ bool TV::StartTV(ProgramInfo *tvrec, uint flags,
                 startSysEventSent = true;
                 startLivetvEventSent = true;
                 gCoreContext->SendSystemEvent("LIVETV_STARTED");
+                usleep(gCoreContext->GetNumSetting("LiveTVWaitMS", 0)*1000);
             }
 
             LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "tv->LiveTV() -- end");
@@ -7479,6 +7480,7 @@ void TV::SwitchInputs(PlayerContext *ctx,
         delete testrec;
     }
 
+    usleep(gCoreContext->GetNumSetting("LiveTVWaitMS", 0)*1000);
     UnpauseLiveTV(ctx);
     UpdateOSDInput(ctx);
 
@@ -7795,6 +7797,7 @@ void TV::ChangeChannel(PlayerContext *ctx, ChannelChangeDirection direction)
     if (ctx->player)
         ctx->player->GetAudio()->Reset();
 
+    usleep(gCoreContext->GetNumSetting("LiveTVWaitMS", 0)*1000);
     UnpauseLiveTV(ctx);
 
     if (oldinputname != ctx->recorder->GetInput())
@@ -7964,6 +7967,7 @@ void TV::ChangeChannel(PlayerContext *ctx, uint chanid, const QString &chan)
     if (ctx->player)
         ctx->player->GetAudio()->Reset();
 
+    usleep(gCoreContext->GetNumSetting("LiveTVWaitMS", 0)*1000);
     UnpauseLiveTV(ctx, chanid && GetQueuedChanID());
 
     if (oldinputname != ctx->recorder->GetInput())
diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp
index e0551ef2840..b963a8dce87 100644
--- a/mythtv/programs/mythfrontend/globalsettings.cpp
+++ b/mythtv/programs/mythfrontend/globalsettings.cpp
@@ -1810,6 +1810,21 @@ static HostSpinBoxSetting *LiveTVIdleTimeout()
     return gs;
 }
 
+static HostSpinBoxSetting *LiveTVWaitMS()
+{
+    HostSpinBoxSetting *gs = new HostSpinBoxSetting("LiveTVWaitMS", 0, 10000, 100);
+
+    gs->setLabel(PlaybackSettings::tr("Live TV wait (milliseconds)"));
+
+    gs->setValue(0);
+
+    gs->setHelpText(PlaybackSettings::tr("Wait the specified number of milliseconds "
+                                         "before beginning playback of Live TV "
+                                         "to avoid stuttering during the first minute"));
+    return gs;
+}
+
+
 // static HostCheckBoxSetting *PlaybackPreview()
 // {
 //     HostCheckBoxSetting *gc = new HostCheckBoxSetting("PlaybackPreview");
@@ -4224,6 +4239,7 @@ void PlaybackSettings::Load(void)
     general->addChild(UseProgStartMark());
     general->addChild(AutomaticSetWatched());
     general->addChild(ContinueEmbeddedTVPlay());
+    general->addChild(LiveTVWaitMS());
     general->addChild(LiveTVIdleTimeout());
 
 #if CONFIG_DEBUGTYPE
