On the first Google TV Streamer, Bluetooth headphones were roughly 200–250 ms late in Netflix while YouTube remained in sync. The usual sound settings did not fix it. The same failure and workaround were later reproduced on a second Streamer with different headphones and a different Bluetooth codec.
The evidence pointed to Netflix using Android's tunneled playback path over Bluetooth. On both devices, that path used hardware A/V sync, and the observed behavior was consistent with the headphones' presentation delay not being compensated correctly. Adding Netflix's own platform capability below forced non-tunneled playback over Bluetooth:
"tunnelModeWithBTSetting": "disable"After restarting Netflix, the video decoder reported INPUT_TUNNEL_MODE OFF, Netflix moved off the DIRECT | HW_AV_SYNC audio route, and lip sync was correct.
This is an unsupported workaround, not an official Google or Netflix fix. Back up the existing setting before changing it.
- Google TV Streamer (
kirkwood) - Android TV 14 / API 34
- Google TV build
UTTK.260317.003 - Netflix
13.1.2 build 26051 - Srhythm NC25 Bluetooth headphones, offering AAC and SBC
- Symptom was application-specific: YouTube was synchronized; Netflix was not
The device names, network addresses, Bluetooth addresses, and account details have been omitted.
The two applications used different playback paths:
| Application | Observed path | Result |
|---|---|---|
| YouTube | Ordinary PCM/deep-buffer A2DP path | Video compensated for Bluetooth delay |
| Netflix | `DIRECT | HW_AV_SYNC`, with tunneled secure video |
Other useful observations:
- The headphones exposed AAC and SBC, but no aptX Low Latency, aptX Adaptive, LDAC, or Opus.
- Android reported that Bluetooth variable-latency mode was enabled at the framework level, but the audio HAL did not support it.
- A2DP hardware offload was disabled.
- Spatial audio, dialogue enhancement, and volume leveling were already off.
- Changing surround output to “Never” did not change the bad Netflix route.
- Switching AAC to SBC reduced the delay somewhat, but did not eliminate it by itself. The controlled AAC retest below showed that the codec change was not the actual fix.
Inspection of the installed Netflix build revealed an explicit platform capability named tunnelModeWithBTSetting and code paths logging:
Tunnel mode with BT is enabled due to platform configTunnel mode with BT is disabled due to platform config
Accepted values are enable, disable, and default.
Install Android SDK Platform Tools and jq on the computer. On the Google TV device, enable Developer options by opening Settings → System → About and selecting Android TV OS build seven times. Then open Settings → System → Developer options → Wireless debugging.
For the first connection, choose Pair device with pairing code on the TV and use the pairing address shown there:
adb pair GOOGLE_TV_IP:PAIRING_PORTEnter the six-digit code from the TV when prompted. Then use the separate IP address and port shown on the main Wireless debugging screen:
adb connect GOOGLE_TV_IP:ADB_PORT
adb devicesWireless-debugging ports can vary. Use the IP address and port shown by the TV.
The commands below preserve every existing field rather than replacing the whole JSON object. They also stop if the existing value is not a valid JSON object:
set -e
ORIGINAL=$(adb shell settings get global nrdp_platform_capabilities | tr -d '\r')
if [ -z "$ORIGINAL" ] || [ "$ORIGINAL" = "null" ]; then
ORIGINAL='{}'
fi
printf '%s\n' "$ORIGINAL" > nrdp_platform_capabilities.backup.json
UPDATED=$(printf '%s' "$ORIGINAL" \
| jq -e -c '
if type == "object" then
. + {"tunnelModeWithBTSetting":"disable"}
else
error("existing capability value is not a JSON object")
end
')
PAYLOAD=$(printf '%s' "$UPDATED" | base64 | tr -d '\n')
adb shell "settings put global nrdp_platform_capabilities \
\"\$(echo '$PAYLOAD' | base64 -d)\""Verify the result:
adb shell settings get global nrdp_platform_capabilitiesThe output should retain the original fields and include:
"tunnelModeWithBTSetting":"disable"adb shell am force-stop com.netflix.ninja
adb shell monkey -p com.netflix.ninja \
-c android.intent.category.LEANBACK_LAUNCHER 1 >/dev/nullThis force-stops and relaunches Netflix. It does not clear the application data or sign the user out.
Play a dialogue-heavy Netflix scene. On the tested MediaTek-based Streamer, the following command confirmed the changed video path:
adb shell logcat -d -v time \
| grep 'set INPUT_TUNNEL_MODE' \
| tail -1Expected result:
set INPUT_TUNNEL_MODE OFF
The exact log tag is platform-specific, so its absence on another device does not prove the workaround failed. The practical test is whether dialogue remains synchronized.
SBC was tested first and made the original tunneled-path delay somewhat smaller, but Netflix still looked out of sync.
After disabling tunnel mode fixed the problem, the headphones were deliberately switched back to AAC while keeping every other relevant setting unchanged. Netflix was restarted and the same kind of dialogue-heavy content was tested again. The device reported all of the following:
- AAC at 44.1 kHz, 16-bit stereo
INPUT_TUNNEL_MODE OFF- an active Netflix PCM/A2DP audio track with flags
0x000, rather than the previous direct/HW-A/V-sync route
Lip sync remained correct. This isolates tunnelModeWithBTSetting=disable as the effective workaround on this setup; SBC was not required. AAC was therefore left enabled.
On 22 August 2026, the same failure was reproduced on a second, separately configured Google TV Streamer while Netflix was playing through JBL Live 780NC headphones. This setup differed from the first in useful ways:
- Netflix was again
13.1.2 build 26051. - The headphones were using LDAC at 96 kHz, 32-bit stereo rather than AAC.
nrdp_platform_capabilitiesagain lackedtunnelModeWithBTSetting.- Netflix had an active
hw_avsync_btoutput withDIRECT | HW_AV_SYNC. - The active Netflix audio track repeatedly logged retrograde timestamp corrections.
After merging "tunnelModeWithBTSetting":"disable" and restarting Netflix,
the decoder logged INPUT_TUNNEL_MODE OFF. The active Netflix audio track moved
to the ordinary ms12_input_deep_buffer A2DP/PCM path, and the user reported
that lip sync was correct.
This does not establish how widespread the bug is, but reproducing the same failure and fix on two Streamers with two headphone models and two codecs makes a headphone-specific cause unlikely. The shared Netflix/Streamer tunneled path is the common factor observed in both cases.
On the tested device, the delay returned three days later and then returned again five days after it was reapplied. The TV had not rebooted, the system build was unchanged, and Netflix had not updated. In both cases, this command showed that tunnelModeWithBTSetting had disappeared:
adb shell settings get global nrdp_platform_capabilitiesThe second recurrence exposed the exact writer. Google TV Streamer includes a persistent, privileged MediaTek service named com.mediatek.nfxservice. Inspection of its installed code showed that it listens for display changes and HDMI-audio hotplug events. Its HDR-capability check writes a complete, hard-coded nrdp_platform_capabilities object rather than preserving unknown fields, so every such write removes tunnelModeWithBTSetting.
The device log captured the reset trigger directly:
NFXService: onDisplayChanged
NFXService: HDR_NOT_APPLICABLE
NFXService: HPD Connect
This can happen during an HDMI/display transition such as a TV wake, reconnect, or input-mode change; it does not require a reboot or software update.
If the delay returns, inspect the value above first:
- If
tunnelModeWithBTSettingis missing, repeat steps 2 and 3. Reapplying the field and restarting Netflix restored correct sync immediately on the tested device. - If the field is still set to
disable, do not assume the same cause. Capture the current playback route and investigate it as a separate regression.
Do not disable com.mediatek.nfxservice as a workaround. It also manages Netflix audio/HDR capabilities, HDMI CEC state, and Netflix remote-button behavior. A narrowly scoped observer that merges only the missing field back would be safer, but that requires a separately installed helper with privileged settings permission and is not part of this procedure.
Wireless-debugging ports can also change. If a previously working address no longer connects, this command can reveal the currently advertised connection endpoint:
adb mdns servicesLook for the Google TV device's _adb-tls-connect._tcp entry, then connect to the IP address and port shown there.
The manual workaround is safer and simpler for a one-off occurrence. On the tested Streamer, however, MediaTek's service removed the field repeatedly after normal display changes. A small open-source helper was therefore tested as an optional self-healing guard.
The guard included in this Gist:
- Watches only the Settings Provider URI for
nrdp_platform_capabilities. - Parses the current JSON and adds only
"tunnelModeWithBTSetting":"disable"when it is missing or different. - Leaves missing or invalid JSON untouched rather than replacing it.
- Uses
JobScheduler, so it does not poll or keep a process running. - Re-arms the observer after each change and schedules it again after boot.
- Requests no Internet, storage, Bluetooth, account, microphone, notification, or accessibility permission.
It does require Android's broad WRITE_SECURE_SETTINGS permission. The source
uses that permission for one global key, but anyone considering this workaround
should inspect and build the source rather than installing an unknown APK.
Android initially places an unlaunched sideload in the NEVER standby bucket
and can later defer jobs for rarely used apps. The tested installation therefore
also uses a battery-optimization exemption. This keeps the event-driven job
eligible; it does not make the helper poll or run continuously.
See the companion netflix-bt-guard-source.md
file in this Gist. Recreate its layout and build it using build.sh, then
install and initialize it:
adb install -r netflix-bt-guard.apk
adb shell pm grant io.github.elitan.netflixbtguard \
android.permission.WRITE_SECURE_SETTINGS
adb shell dumpsys deviceidle whitelist \
+io.github.elitan.netflixbtguard
adb shell am start \
-n io.github.elitan.netflixbtguard/.StartActivityOn the first tested device, a simulated overwrite was repaired on the first
check. A real sleep/wake cycle then caused com.mediatek.nfxservice to
regenerate the capability object three times; the guard restored the field
after every write, generally within about 0.5 seconds.
The same guard was then installed on the second Streamer. A controlled removal of the field was repaired on the third 200 ms check, about 0.4 seconds later. Netflix continued playing through the corrected non-tunneled audio path.
The helper does not restart Netflix. If Netflix was already running and cached the bad configuration before the guard repaired it, close and reopen Netflix once.
To remove the helper completely:
adb shell dumpsys deviceidle whitelist \
-io.github.elitan.netflixbtguard
adb uninstall io.github.elitan.netflixbtguardUninstalling does not restore the original capability JSON. Use the separate revert procedure below if that is also desired.
To restore the original Netflix capability object:
ORIGINAL=$(tr -d '\r\n' < nrdp_platform_capabilities.backup.json)
PAYLOAD=$(printf '%s' "$ORIGINAL" | base64 | tr -d '\n')
adb shell "settings put global nrdp_platform_capabilities \
\"\$(echo '$PAYLOAD' | base64 -d)\""
adb shell am force-stop com.netflix.ninja
adb shell monkey -p com.netflix.ninja \
-c android.intent.category.LEANBACK_LAUNCHER 1 >/dev/null- A Netflix or Google TV update may overwrite or stop honoring this setting.
- The same failure and one-field workaround were reproduced on two separate Google TV Streamers using Srhythm NC25/AAC and JBL Live 780NC/LDAC respectively. This reduces the likelihood of a headphone-specific cause but does not prove that every Streamer is affected.
- MediaTek's privileged Netflix support service removes the value when it regenerates the capability object after HDMI/display changes. On the first device, this removal was reproduced twice without a reboot or application update.
- Do not copy another person's complete
nrdp_platform_capabilitiesJSON; merge only the one field so device-specific capabilities remain intact. - Clearing Netflix data and factory-resetting the Streamer were not required.
- Turn Wireless debugging off after testing.