Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fragParsingError Demux #6379

Open
5 tasks done
gabinfinity opened this issue Apr 25, 2024 · 1 comment
Open
5 tasks done

fragParsingError Demux #6379

gabinfinity opened this issue Apr 25, 2024 · 1 comment

Comments

@gabinfinity
Copy link

What version of Hls.js are you using?

1.5.8

What browser (including version) are you using?

Chrome lastest version

What OS (including version) are you using?

Windows 10

Test stream

No response

Configuration

import { useVideoSettingsStore } from "@/features/player/store/videoSettings.slice";
import { ISource, ISubtitle } from "@/features/player/types";
import { removeDuplicateObjects, sortVideoQualities } from "@/utils/helper";
import Hls, { Level } from "hls.js";
import { useRouter } from "next/router";
import React, { useEffect } from "react";
import { useContextSelector } from "use-context-selector";
import { GlobalStateContext } from "../../contexts/GlobalStateContext";
import useVideoSourcesStore from "../../store/sources.slice";
import { useVideoStatusStore } from "../../store/videoStatus.slice";
import { shouldPlayHls, sortDefaultLanguage } from "../../utils/helper";

const convertLevelToQuality = (level: Level): ISource => {
  return { quality: `${level.height}p`.replace("2160p", "4K"), url: level.uri, type: "m3u8" };
};

const canPlayHlsNatively = (video: HTMLVideoElement): boolean => {
  if (Hls.isSupported()) return false; // no need to play natively
  return !!video.canPlayType("application/vnd.apple.mpegurl");
}

function VideoHls() {
  const router = useRouter();
  const locale = router?.locale || "en";
  const hls = React.useRef<Hls | null>(null);
  const setPaused = useVideoStatusStore((s) => s.setPaused);
  const { playerRef, setGlobalState } = useContextSelector(GlobalStateContext, (s) => ({
    playerRef: s.playerRef,
    setGlobalState: s.setGlobalState
  }));
  const { setHandleChangeQuality, currentSource, setCurrentSource, setCurrentQuality } =
    useVideoSourcesStore((s) => ({
      setHandleChangeQuality: s.setHandleChangeQuality,
      setCurrentSource: s.setCurrentSource,
      currentSource: s.currentSource,
      setCurrentQuality: s.setCurrentQuality
    }));
  const { currentAudio, audios, setState } = useVideoSettingsStore((s) => ({
    currentAudio: s.currentAudio,
    audios: s.audios,
    setState: s.setState
  }));
  useEffect(() => {
    const _handleChangeQuality = (choosenQuality: ISource) => {
      try {
        if (shouldPlayHls(choosenQuality)) {
          if (
            !playerRef.current ||
            canPlayHlsNatively(playerRef.current) ||
            !hls.current
          ) {
            setCurrentQuality(choosenQuality);
            setCurrentSource(choosenQuality);
            return; // nothing to change
          }
          if (hls.current.levels.length > 1) {
            const levelIndex = hls.current.levels.findIndex((v) => v.uri === choosenQuality.url);
            if (levelIndex !== -1) {
              hls.current.currentLevel = levelIndex;
              hls.current.loadLevel = levelIndex;
              const level = hls.current.levels[levelIndex];
              if (!level?.height) return;
              setCurrentQuality(convertLevelToQuality(level));
            }
          } else {
            hls.current.currentLevel = -1;
            hls.current.loadLevel = -1;
            setCurrentQuality(choosenQuality);
            setCurrentSource(choosenQuality);
          }
        } else {
          if (hls.current !== null) {
            hls.current.destroy();
            hls.current = null;
          }
          setCurrentQuality(choosenQuality);
          setCurrentSource(choosenQuality);
        }
      } catch (error: any) {
        console.log("error: ", error?.message);
      }
    };
    setHandleChangeQuality(_handleChangeQuality);
  }, [playerRef, setHandleChangeQuality, setCurrentQuality, setCurrentSource]);
  useEffect(() => {
    if (!playerRef.current || !currentSource) return;
    if (canPlayHlsNatively(playerRef.current)) {
      // HLS supported natively by browser
      playerRef.current.src = currentSource?.url;
    } else {
      if (Hls.isSupported()) {
        const initPlayer = async () => {
          if (hls.current !== null) hls.current.destroy();
          let _hls: Hls;
          _hls = new Hls({ enableWorker: false });
          if (playerRef.current !== null) _hls.attachMedia(playerRef.current);
          _hls.loadSource(currentSource?.url);
          _hls.on(Hls.Events.MANIFEST_PARSED, async () => {
            playerRef.current?.play().catch(() => {
              console.warn("User must interact before playing the video.");
              setPaused(true);
            });
            if (!_hls) return;
            if (_hls.levels?.length) {
              const levels: ISource[] = _hls.levels
                .filter((level) => level.height)
                .sort((a, b) => b.height - a.height)
                .map((level) => convertLevelToQuality(level));
              setGlobalState((prev) => {
                return {
                  ...prev,
                  sources: sortVideoQualities(
                    removeDuplicateObjects([...prev.sources, ...levels], "url") as ISource[]
                  )
                };
              });
            }
          });
          _hls.on(Hls.Events.LEVEL_SWITCHED, () => {
            if (!_hls) return;
            const level = _hls.levels[_hls.currentLevel];
            if (!level.height) return;
            const quality: ISource = convertLevelToQuality(level);
            setCurrentQuality(quality);
          });
          _hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, async (_, event) => {
            const { localeToLanguage } = await import("@/constants");
            const modifiedAudios = sortDefaultLanguage(
              event.audioTracks.map((track, index) => ({
                lang: `${track.lang}${index}`,
                language: track.name
              })) as ISubtitle[],
              locale,
              localeToLanguage[locale as keyof typeof localeToLanguage]
            );
            setState({
              audios: modifiedAudios,
              // @ts-ignore
              currentAudio: modifiedAudios[_hls.audioTrack >= 0 ? _hls.audioTrack : 0]?.lang
            });
          });
          _hls.on(Hls.Events.ERROR, function (_event, data) {
            console.error("Hls error: ", _event, data);
            if (data.fatal) {
              switch (data.type) {
                case Hls.ErrorTypes.NETWORK_ERROR:
                  _hls.startLoad();
                  break;
                case Hls.ErrorTypes.MEDIA_ERROR:
                  _hls.recoverMediaError();
                  break;
                default:
                  break;
              }
            }
          });
          hls.current = _hls;
        };
        initPlayer();
      } else {
        console.log("HLS is not supported on this device/browser");
      }
    }
    return () => {
      if (hls.current !== null) {
        hls.current.destroy();
        hls.current = null;
      }
    };
  }, [playerRef, currentSource, setPaused, locale, setState, setCurrentQuality, setGlobalState]);
  useEffect(() => {
    if (!currentAudio || !Boolean(audios?.length)) return;
    let currentAudioTrack = audios?.findIndex((audio) => audio.lang === currentAudio);
    if (currentAudioTrack === undefined || currentAudioTrack === -1) return;
    if (!hls?.current) return;
    hls.current.audioTrack = currentAudioTrack;
  }, [audios, currentAudio]);
  return null;
}

export default VideoHls;

Additional player setup steps

No response

Checklist

Steps to reproduce

  1. Go to https://www.braflix.video/movie/438631?admin=1z4z1p1p1
  2. Open the player and click in CLOUD icon
  3. Select Golf option

Expected behaviour

HLS should play fine

What actually happened?

HLS doesnt play and i got console error spam

Console output

861.31312f4eb2a7d4c4.js:1 Hls error:  hlsError 
{type: 'mediaError', details: 'fragParsingError', fatal: false, error: Error: Found 571 TS packet/s that do not start with 0x47
    at i2.demux (https://www.braflix.video…, reason: 'Found 571 TS packet/s that do not start with 0x47', …}

Chrome media internals output

Hi, im having this issue on my website

861.31312f4eb2a7d4c4.js:1 Hls error:  hlsError 
{type: 'mediaError', details: 'fragParsingError', fatal: false, error: Error: Found 571 TS packet/s that do not start with 0x47
    at i2.demux (https://www.braflix.video…, reason: 'Found 571 TS packet/s that do not start with 0x47', …}
@gabinfinity gabinfinity added Bug Needs Triage If there is a suspected stream issue, apply this label to triage if it is something we should fix. labels Apr 25, 2024
@robwalch robwalch added Works as expected Stream Issue and removed Bug Needs Triage If there is a suspected stream issue, apply this label to triage if it is something we should fix. labels Apr 25, 2024
@robwalch
Copy link
Collaborator

robwalch commented Apr 25, 2024

This is behaving as expected. The logs are clear about what the media error is - the segments are invalid and the error is fatal. The spamming is a result of calling recoverMediaError which only results in the error sequence repeating itself:

 case Hls.ErrorTypes.MEDIA_ERROR:
    _hls.recoverMediaError();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants