shaka-project / shaka-player

JavaScript player library / DASH & HLS client / MSE-EME player
Apache License 2.0
7.23k stars 1.34k forks source link

Shaka Error MEDIA.TRANSMUXING_FAILED received since v4.4.0 #6322

Closed 0x24D closed 8 months ago

0x24D commented 8 months ago

Have you read the FAQ and checked for duplicate open issues? Yes

If the problem is related to FairPlay, have you read the tutorial?

N/A

What version of Shaka Player are you using?

4.7.9

Can you reproduce the issue with our latest release version? Yes

Can you reproduce the issue with the latest code from main? Yes

Are you using the demo app or your own custom app? Custom

If custom app, can you reproduce the issue using our demo app? Yes

What browser and OS are you using? Browser: Firefox 115.8.0esr OS: Arch Linux

For embedded devices (smart TVs, etc.), what model and firmware version are you using? N/A

What are the manifest and license server URIs?

hls field from https://pipedapi.adminforge.de/streams/w9uJg68CV4g

What configuration are you using? What is the output of player.getConfiguration()?

{
  "drm": {
    "retryParameters": {
      "maxAttempts": 2,
      "baseDelay": 1000,
      "backoffFactor": 2,
      "fuzzFactor": 0.5,
      "timeout": 30000,
      "stallTimeout": 5000,
      "connectionTimeout": 10000
    },
    "servers": {},
    "clearKeys": {},
    "advanced": {},
    "delayLicenseRequestUntilPlayed": false,
    "persistentSessionOnlinePlayback": false,
    "persistentSessionsMetadata": [],
    "logLicenseExchange": false,
    "updateExpirationTime": 1,
    "preferredKeySystems": [],
    "keySystemsMapping": {},
    "parseInbandPsshEnabled": false,
    "minHdcpVersion": "",
    "ignoreDuplicateInitData": true
  },
  "manifest": {
    "retryParameters": {
      "maxAttempts": 2,
      "baseDelay": 1000,
      "backoffFactor": 2,
      "fuzzFactor": 0.5,
      "timeout": 30000,
      "stallTimeout": 5000,
      "connectionTimeout": 10000
    },
    "availabilityWindowOverride": null,
    "disableAudio": false,
    "disableVideo": false,
    "disableText": false,
    "disableThumbnails": false,
    "defaultPresentationDelay": 0,
    "segmentRelativeVttTiming": false,
    "raiseFatalErrorOnManifestUpdateRequestFailure": false,
    "dash": {
      "clockSyncUri": "",
      "ignoreDrmInfo": false,
      "disableXlinkProcessing": false,
      "xlinkFailGracefully": false,
      "ignoreMinBufferTime": false,
      "autoCorrectDrift": true,
      "initialSegmentLimit": 1000,
      "ignoreSuggestedPresentationDelay": false,
      "ignoreEmptyAdaptationSet": false,
      "ignoreMaxSegmentDuration": false,
      "keySystemsByURI": {
        "urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b": "org.w3.clearkey",
        "urn:uuid:e2719d58-a985-b3c9-781a-b030af78d30e": "org.w3.clearkey",
        "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed": "com.widevine.alpha",
        "urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95": "com.microsoft.playready",
        "urn:uuid:79f0049a-4098-8642-ab92-e65be0885f95": "com.microsoft.playready",
        "urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb": "com.adobe.primetime"
      },
      "sequenceMode": false,
      "enableAudioGroups": false,
      "multiTypeVariantsAllowed": true
    },
    "hls": {
      "ignoreTextStreamFailures": false,
      "ignoreImageStreamFailures": false,
      "defaultAudioCodec": "mp4a.40.2",
      "defaultVideoCodec": "avc1.42E01E",
      "ignoreManifestProgramDateTime": false,
      "mediaPlaylistFullMimeType": "video/mp2t; codecs=\"avc1.42E01E, mp4a.40.2\"",
      "useSafariBehaviorForLive": true,
      "liveSegmentsDelay": 3,
      "sequenceMode": true,
      "ignoreManifestTimestampsInSegmentsMode": false,
      "disableCodecGuessing": false,
      "allowLowLatencyByteRangeOptimization": true
    },
    "mss": {
      "sequenceMode": false,
      "keySystemsBySystemId": {
        "9a04f079-9840-4286-ab92-e65be0885f95": "com.microsoft.playready",
        "79f0049a-4098-8642-ab92-e65be0885f95": "com.microsoft.playready"
      }
    }
  },
  "streaming": {
    "retryParameters": {
      "maxAttempts": 2,
      "baseDelay": 1000,
      "backoffFactor": 2,
      "fuzzFactor": 0.5,
      "timeout": 30000,
      "stallTimeout": 5000,
      "connectionTimeout": 10000
    },
    "rebufferingGoal": 2,
    "bufferingGoal": 10,
    "bufferBehind": 30,
    "ignoreTextStreamFailures": false,
    "alwaysStreamText": false,
    "startAtSegmentBoundary": false,
    "gapDetectionThreshold": 0.5,
    "gapJumpTimerTime": 0.25,
    "durationBackoff": 1,
    "safeSeekOffset": 5,
    "stallEnabled": true,
    "stallThreshold": 1,
    "stallSkip": 0.1,
    "useNativeHlsOnSafari": true,
    "inaccurateManifestTolerance": 2,
    "lowLatencyMode": false,
    "autoLowLatencyMode": false,
    "forceHTTPS": false,
    "preferNativeHls": false,
    "updateIntervalSeconds": 1,
    "dispatchAllEmsgBoxes": false,
    "observeQualityChanges": false,
    "maxDisabledTime": 30,
    "parsePrftBox": false,
    "segmentPrefetchLimit": 0,
    "liveSync": false,
    "liveSyncMaxLatency": 1,
    "liveSyncPlaybackRate": 1.1,
    "liveSyncMinLatency": 0,
    "liveSyncMinPlaybackRate": 1,
    "allowMediaSourceRecoveries": true,
    "minTimeBetweenRecoveries": 5
  },
  "mediaSource": {
    "codecSwitchingStrategy": "smooth",
    "sourceBufferExtraFeatures": "",
    "forceTransmux": false,
    "insertFakeEncryptionInInit": true
  },
  "offline": {
    "usePersistentLicense": true,
    "numberOfParallelDownloads": 5
  },
  "abr": {
    "enabled": true,
    "useNetworkInformation": true,
    "defaultBandwidthEstimate": 1000000,
    "switchInterval": 8,
    "bandwidthUpgradeTarget": 0.85,
    "bandwidthDowngradeTarget": 0.95,
    "restrictions": {
      "minWidth": 0,
      "maxWidth": null,
      "minHeight": 0,
      "maxHeight": null,
      "minPixels": 0,
      "maxPixels": null,
      "minFrameRate": 0,
      "maxFrameRate": null,
      "minBandwidth": 0,
      "maxBandwidth": null
    },
    "advanced": {
      "minTotalBytes": 128000,
      "minBytes": 16000,
      "fastHalfLife": 2,
      "slowHalfLife": 5
    },
    "restrictToElementSize": false,
    "restrictToScreenSize": false,
    "ignoreDevicePixelRatio": false,
    "clearBufferSwitch": false,
    "safeMarginSwitch": 0
  },
  "autoShowText": 3,
  "preferredAudioLanguage": "",
  "preferredAudioLabel": "",
  "preferredTextLanguage": "",
  "preferredVariantRole": "",
  "preferredTextRole": "",
  "preferredAudioChannelCount": 2,
  "preferredVideoHdrLevel": "AUTO",
  "preferredVideoLayout": "",
  "preferredVideoLabel": "",
  "preferredVideoCodecs": [],
  "preferredAudioCodecs": [],
  "preferForcedSubs": false,
  "preferSpatialAudio": false,
  "preferredDecodingAttributes": [],
  "restrictions": {
    "minWidth": 0,
    "maxWidth": null,
    "minHeight": 0,
    "maxHeight": null,
    "minPixels": 0,
    "maxPixels": null,
    "minFrameRate": 0,
    "maxFrameRate": null,
    "minBandwidth": 0,
    "maxBandwidth": null
  },
  "playRangeStart": 0,
  "playRangeEnd": null,
  "cmcd": {
    "enabled": false,
    "sessionId": "",
    "contentId": "",
    "useHeaders": false
  },
  "cmsd": {
    "enabled": true,
    "applyMaximumSuggestedBitrate": true,
    "estimatedThroughputWeightRatio": 0.5
  },
  "lcevc": {
    "enabled": false,
    "dynamicPerformanceScaling": true,
    "logLevel": 0,
    "drawLogo": false
  },
  "ads": {
    "customPlayheadTracker": false
  }
}

What did you do?

  1. Add Manifest URL as custom content in demo app
  2. Click 'Play'

What did you expect to happen? Livestream to play normally, like it did before v4.4.0

What actually happened?

Livestream failed to load. Shaka Error: MEDIA.TRANSMUXING_FAILED received

Extra information Additionally, after git bisecting the custom app and shaka-player this error was introduced by https://github.com/shaka-project/shaka-player/commit/eec25b2c6efc1cccc35509131c37bd4569d54b9e - https://github.com/TeamPiped/Piped/issues/3407#issuecomment-1974866164

joeyparrish commented 8 months ago

Your bisect suggests that our old, third-party transmuxer (mux.js) could handle this content, but that our own transmuxer can't.

@avelad, when you are available, can you look into this?

joeyparrish commented 8 months ago

@0x24D, while you are waiting for a fix, you may use v4.3.x, which is still being bugfixed today because of the Cast platform's use of it.

avelad commented 8 months ago

@0x24D you url returns a 403, can you fix it? Thanks!

0x24D commented 8 months ago

@avelad I've updated the manifest URL in the original post. It looks like it'll expire in 6 hours so let me know if you need a new one after then.

avelad commented 8 months ago

It seems that for the audio segments we are not able to do the parsing correctly, and we issue this warning: https://github.com/shaka-project/shaka-player/blob/main/lib/util/ts_parser.js#L202, we should investigate the syncOffset function to see where the error is. @joeyparrish can you review it? Thanks!

joeyparrish commented 8 months ago

@0x24D, I need to capture a failed segment to compare our parser with another one. Can you refresh the URL for me, please? Or send a zip of the TS audio segments? I'm not sure if when you'll see this, what time zone you're in, or when I'll see your reply...

0x24D commented 8 months ago

@joeyparrish I've updated the manifest URL again

joeyparrish commented 8 months ago

Got it, thanks!

joeyparrish commented 8 months ago

Your first TS audio segment does not seem to be valid. Our parser doesn't understand it, and neither does an independent web-based parser called https://thumb.co.il/.

Looking at the placement of start codes in the first 1000 bytes of the segment, I see these positions for 0x47:

Not all of those will be actual start codes, but each TS packet should begin with 0x47, and those packets should each be 188 bytes. Here are the distances between those with their most likely neighbors:

Since none of those 0x47 bytes are 188 bytes away from any others, none of the first 1000 bytes of the segment could realistically be the start of TS packets within the segment.

The parser looks for three evenly spaced 0x47 bytes in a "scan window", which maxes at 1000 bytes, then chooses the first of those three as the start of the first TS packet. If I increase the "scan window" to the entire segment, I still find no candidates.

So, as far as I can tell, this is an encoding issue, and you should look at your transcoder/transmuxer on the server, if you are transcoding/transmuxing the original streams.

Have you considered streaming fMP4 instead of TS? It's generally a better format for streaming, has clearer structure and metadata, and doesn't require transmuxing in the player.

0x24D commented 8 months ago

I've had a look, after working out how everything works, and the error occurs with the raw input data too. We take the data and just proxy it through a web server (no transcoding/transmuxing) so the data coming in is the same data coming out.

The manifest we give to shaka-player is a list of #EXT-X-INDEPENDENT-SEGMENTS as #EXT_X_MEDIA:URIs. These URIs themselves are a list of segments seg.ts. Somehow two of the #EXT_X_MEDIA:URIs are chosen and used, one for video and one for audio. The video URI works fine whereas the audio URI fails as you've seen before. I can also confirm what you've seen with the 0x47 bytes.

file detects the audio segments as seg.ts: Audio file with ID3 version 2.3.0, contains:\012- MPEG ADTS, AAC, v4 LC, 44.1 kHz, stereo and mpv plays them correctly: [cplayer] (+) Audio --aid=1 (aac 2ch 44100Hz) [cplayer] AO: [pulse] 44100Hz stereo 2ch float

joeyparrish commented 8 months ago

Then it looks like it's not TS at all, but raw/packed AAC being mislabeled as TS.

CHaNGeTe commented 8 months ago

Then it looks like it's not TS at all, but raw/packed AAC being mislabeled as TS.

Having the same exact issue with other stream. Using 4.3.15 also helps (mux.js)

Stream coming from Akamai, so seems is quite common practice (even it is wrong)

CHaNGeTe commented 8 months ago

https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.messages#.HlsSegmentFormat

TS_AAC stringAAC low complexity packed MPEG-2 transport stream (AAC-LC).

@joeyparrish

joeyparrish commented 8 months ago

That enum from the Cast SDK both doesn't have relevance for this GitHub repo and doesn't match your content. Your audio content is not MPEG-2 transport stream.

If there's no explicit MIME type in the playlist, we have to guess what format it is based on the extension. The extension says TS, but it's not. How should we know it's containerless AAC in this situation?

avelad commented 8 months ago

@0x24D you url returns a 403, can you fix it? Thanks!

0x24D commented 8 months ago

@avelad To stop the URL from 403ing I've updated the manifest URL to be where I get the manifest from

avelad commented 8 months ago

Although technically, as @joeyparrish says, it is bad content, I am going to do a little workaround to support this case since mux.js and hls.js support it

joeyparrish commented 8 months ago

Thank you @avelad ! Even for bad content, I'm always happy to have a workaround if it doesn't complicate things too much. And I trust your judgement.