<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dennis Fan</title>
    <description>The latest articles on DEV Community by Dennis Fan (@flbdennis).</description>
    <link>https://dev.to/flbdennis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3970970%2F5e9c6bfa-e3e8-44fb-97df-b57c3da9a8fc.webp</url>
      <title>DEV Community: Dennis Fan</title>
      <link>https://dev.to/flbdennis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/flbdennis"/>
    <language>en</language>
    <item>
      <title>Your M3U8 Link Is Not Broken Until You Test It in a Browser</title>
      <dc:creator>Dennis Fan</dc:creator>
      <pubDate>Mon, 08 Jun 2026 05:26:49 +0000</pubDate>
      <link>https://dev.to/flbdennis/your-m3u8-link-is-not-broken-until-you-test-it-in-a-browser-5h9j</link>
      <guid>https://dev.to/flbdennis/your-m3u8-link-is-not-broken-until-you-test-it-in-a-browser-5h9j</guid>
      <description>&lt;p&gt;Most M3U8 problems look the same at first: the video does not play, the downloader fails, the converter throws an error, or a TS merge tool gives you a useless file. But those failures do not always mean the playlist is bad.&lt;/p&gt;

&lt;p&gt;Before you try to download, convert, or merge anything, test the direct HLS playlist in a browser. I built a free browser-side M3U8 player for exactly that quick check: &lt;a href="https://metistools.com/m3u8-player" rel="noopener noreferrer"&gt;https://metistools.com/m3u8-player&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The important word is direct. A video page URL is not the same thing as an M3U8 URL. A useful test link usually looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com/live/master.m3u8&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or sometimes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://cdn.example.com/video/index.m3u8?token=...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you paste a normal watch page into an M3U8 player, the player cannot magically find a private playlist behind the page. You need the actual playlist URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why browser testing matters
&lt;/h2&gt;

&lt;p&gt;VLC, ffmpeg, server-side scripts, and many M3U8 downloader tools do not behave like Chrome, Edge, Firefox, or Safari. A browser has to follow browser rules: CORS, HTTPS, MIME type, MediaSource support, codec support, cookies, redirects, and token expiry.&lt;/p&gt;

&lt;p&gt;That is why a stream can work in VLC but fail in Chrome. It is also why an M3U8-to-MP4 converter can fail even when the first playlist URL opens fine. The real problem may be a segment URL, a missing CORS header, an expired signed URL, or a codec the browser cannot decode.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical 60-second check
&lt;/h2&gt;

&lt;p&gt;Here is the flow I use before touching downloader, converter, or TS merge tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Paste the direct .m3u8 URL into a browser-side HLS player.&lt;/li&gt;
&lt;li&gt;Confirm the master playlist loads.&lt;/li&gt;
&lt;li&gt;Check whether the media playlist and first segments load.&lt;/li&gt;
&lt;li&gt;Watch for CORS, 403, 404, MIME type, or codec errors.&lt;/li&gt;
&lt;li&gt;Compare Chrome/Edge with Safari if you can.&lt;/li&gt;
&lt;li&gt;If the URL is signed, test again after a few minutes to see whether it expires.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the playlist loads but segments fail, the first URL is probably not the real issue. Look at the segment domain, relative paths, token rules, and CORS headers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common patterns
&lt;/h2&gt;

&lt;p&gt;A few patterns show up again and again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playlist opens, but segments return 403: the token may not apply to segment URLs.&lt;/li&gt;
&lt;li&gt;Playlist works in Safari, but not Chrome: native HLS and JavaScript HLS do not hit the same browser path.&lt;/li&gt;
&lt;li&gt;Downloader fails halfway: some later segment may be expired, blocked, or missing.&lt;/li&gt;
&lt;li&gt;Converter creates a broken MP4: the playlist may include discontinuities, encryption, missing segments, or unsupported codecs.&lt;/li&gt;
&lt;li&gt;Everything worked yesterday: the CDN, token expiry, or source permission may have changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this means you should bypass access rules. If a stream is private, DRM-protected, or not yours to test, the correct fix is permission or source-side configuration, not a workaround.&lt;/p&gt;

&lt;h2&gt;
  
  
  When a simple M3U8 player is enough
&lt;/h2&gt;

&lt;p&gt;For many checks, you do not need a heavy toolchain. You just need to know whether the browser can load the playlist and start playback.&lt;/p&gt;

&lt;p&gt;That is where MetisTools helps: paste a public or authorized M3U8 URL, play it in the browser, and use the playback log as a quick signal before going deeper.&lt;/p&gt;

&lt;p&gt;Try it here: &lt;a href="https://metistools.com/m3u8-player" rel="noopener noreferrer"&gt;https://metistools.com/m3u8-player&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If playback fails there too, you have a useful clue before spending time on m3u8 download, m3u8 to mp4 conversion, or TS segment merging.&lt;/p&gt;

&lt;p&gt;Source note: this article is adapted from my original M3U8 browser testing guide: &lt;a href="https://github.com/flbdennis/m3u8player/blob/main/guides/test-m3u8-stream-in-browser.md" rel="noopener noreferrer"&gt;https://github.com/flbdennis/m3u8player/blob/main/guides/test-m3u8-stream-in-browser.md&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hls</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Practical Notes on M3U8 and HLS Playback Issues</title>
      <dc:creator>Dennis Fan</dc:creator>
      <pubDate>Sat, 06 Jun 2026 11:28:35 +0000</pubDate>
      <link>https://dev.to/flbdennis/practical-notes-on-m3u8-and-hls-playback-issues-oa</link>
      <guid>https://dev.to/flbdennis/practical-notes-on-m3u8-and-hls-playback-issues-oa</guid>
      <description>&lt;p&gt;I have been collecting some practical notes around M3U8 and HLS playback recently.&lt;/p&gt;

&lt;p&gt;At first, this topic may sound simple: put an M3U8 URL into a player and play the video.&lt;/p&gt;

&lt;p&gt;But in real projects, M3U8 playback is often not that simple. When a video does not play, the problem is not always the player. It can also be the playlist, media segments, browser support, server headers, CORS, HTTPS, or codec compatibility.&lt;/p&gt;

&lt;p&gt;This post is a short collection of practical things I think are useful when working with M3U8 or HLS in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is M3U8?
&lt;/h2&gt;

&lt;p&gt;M3U8 is a playlist file format.&lt;/p&gt;

&lt;p&gt;With a normal MP4 video, the URL usually points to one video file.&lt;/p&gt;

&lt;p&gt;With M3U8, the URL usually points to a playlist. That playlist then points to many smaller media files, often called media segments.&lt;/p&gt;

&lt;p&gt;So instead of loading one big video file, the browser or player loads a playlist first, then loads the media segments listed inside it.&lt;/p&gt;

&lt;p&gt;That is why M3U8 playback can fail in more than one place.&lt;/p&gt;

&lt;p&gt;The playlist may load, but the segments may fail.&lt;/p&gt;

&lt;p&gt;The first few segments may load, but later ones may be blocked.&lt;/p&gt;

&lt;p&gt;The URL may work in one browser, but fail in another.&lt;/p&gt;

&lt;p&gt;This is one reason why debugging M3U8 playback can feel confusing at first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HLS?
&lt;/h2&gt;

&lt;p&gt;HLS means HTTP Live Streaming.&lt;/p&gt;

&lt;p&gt;It is a streaming technology created by Apple. It is commonly used for live streams and on-demand video.&lt;/p&gt;

&lt;p&gt;HLS usually uses an M3U8 playlist to describe the stream.&lt;/p&gt;

&lt;p&gt;A simple way to think about it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HLS is the streaming technology.&lt;/li&gt;
&lt;li&gt;M3U8 is the playlist format used by HLS.&lt;/li&gt;
&lt;li&gt;Media segments are the small video or audio files listed inside the playlist.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So when people say “M3U8 player”, they usually mean a player that can play HLS streams from an M3U8 URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser support matters
&lt;/h2&gt;

&lt;p&gt;Browser support is one of the first things to check.&lt;/p&gt;

&lt;p&gt;Safari usually supports HLS directly. That means Safari can often play an M3U8 URL without extra JavaScript libraries.&lt;/p&gt;

&lt;p&gt;Chrome, Firefox, and Edge usually need help from a library like hls.js.&lt;/p&gt;

&lt;p&gt;hls.js is a JavaScript library that helps browsers play HLS streams when they do not support HLS directly.&lt;/p&gt;

&lt;p&gt;So if a stream works in Safari but not in Chrome, that does not always mean the stream is broken. It may simply mean the page needs proper HLS support for that browser.&lt;/p&gt;

&lt;p&gt;When testing an M3U8 URL, I usually ask these questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this browser support HLS directly?&lt;/li&gt;
&lt;li&gt;Do I need hls.js?&lt;/li&gt;
&lt;li&gt;Can the browser load the M3U8 playlist?&lt;/li&gt;
&lt;li&gt;Can the browser load the media segments?&lt;/li&gt;
&lt;li&gt;Are the video and audio codecs supported?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These checks are basic, but they solve many common problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  CORS is a common problem
&lt;/h2&gt;

&lt;p&gt;CORS means Cross-Origin Resource Sharing.&lt;/p&gt;

&lt;p&gt;In simple words, CORS is a browser security rule that controls whether a web page can request resources from another domain.&lt;/p&gt;

&lt;p&gt;For example, your website may be on:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But the M3U8 stream may be on:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://video-server.com/stream.m3u8&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If the video server does not allow cross-origin requests, the browser may block the playlist or media segments.&lt;/p&gt;

&lt;p&gt;This is very common with M3U8 playback.&lt;/p&gt;

&lt;p&gt;The confusing part is that the M3U8 URL may still open in a browser tab. But opening the URL directly is not the same as loading it from another web page.&lt;/p&gt;

&lt;p&gt;So when an M3U8 player does not work, CORS should be one of the first things to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  The playlist is only the starting point
&lt;/h2&gt;

&lt;p&gt;Another common mistake is only checking the M3U8 file.&lt;/p&gt;

&lt;p&gt;The M3U8 playlist is just the entry point. The actual video data usually comes from the segment URLs inside the playlist.&lt;/p&gt;

&lt;p&gt;So even if the playlist loads successfully, playback can still fail if the segments are blocked, missing, expired, or not allowed by CORS.&lt;/p&gt;

&lt;p&gt;When debugging, it is useful to check the full playback chain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The main M3U8 URL&lt;/li&gt;
&lt;li&gt;The child playlist URLs, if there are multiple quality levels&lt;/li&gt;
&lt;li&gt;The media segment URLs&lt;/li&gt;
&lt;li&gt;HTTP status codes&lt;/li&gt;
&lt;li&gt;CORS headers&lt;/li&gt;
&lt;li&gt;HTTPS issues&lt;/li&gt;
&lt;li&gt;Browser console errors&lt;/li&gt;
&lt;li&gt;Network errors in DevTools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives a much clearer picture than only looking at the player UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTPS and mixed content
&lt;/h2&gt;

&lt;p&gt;Mixed content is another common issue.&lt;/p&gt;

&lt;p&gt;Mixed content happens when a secure HTTPS page tries to load insecure HTTP resources.&lt;/p&gt;

&lt;p&gt;For example, your page may be:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com/player&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But the stream may be:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://video-server.com/stream.m3u8&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Modern browsers may block this for security reasons.&lt;/p&gt;

&lt;p&gt;So if your website uses HTTPS, the M3U8 playlist and its media segments should also use HTTPS.&lt;/p&gt;

&lt;p&gt;This sounds simple, but it is easy to miss when testing different video URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Codec support also matters
&lt;/h2&gt;

&lt;p&gt;A codec is the format used to compress and decode video or audio.&lt;/p&gt;

&lt;p&gt;For web video, common codecs include H.264 for video and AAC for audio.&lt;/p&gt;

&lt;p&gt;Even if the M3U8 playlist is valid and all segments are reachable, playback can still fail if the browser does not support the codec used by the stream.&lt;/p&gt;

&lt;p&gt;This is why two M3U8 URLs can behave very differently.&lt;/p&gt;

&lt;p&gt;One may play correctly because it uses browser-friendly codecs.&lt;/p&gt;

&lt;p&gt;Another may fail because the codec is not supported by the browser or device.&lt;/p&gt;

&lt;p&gt;So when debugging playback, do not only check the URL. Also consider what video and audio formats are inside the stream.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization and expired links
&lt;/h2&gt;

&lt;p&gt;Some M3U8 URLs require authorization.&lt;/p&gt;

&lt;p&gt;That means the stream may only work when the request includes a valid token, cookie, or special header.&lt;/p&gt;

&lt;p&gt;Some URLs also expire after a short time.&lt;/p&gt;

&lt;p&gt;In these cases, the player may work for a while and then suddenly fail.&lt;/p&gt;

&lt;p&gt;This does not always mean the player is broken. It may mean the stream URL is protected, expired, or only allowed in a specific environment.&lt;/p&gt;

&lt;p&gt;For public testing tools, this is important to understand.&lt;/p&gt;

&lt;p&gt;A browser-based playback tool can test whether a URL is playable from the browser, but it cannot bypass access rules set by the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good error messages are important
&lt;/h2&gt;

&lt;p&gt;A simple “video failed to load” message is not very useful.&lt;/p&gt;

&lt;p&gt;A better error message should give the user some direction.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The M3U8 URL may not be reachable.&lt;/li&gt;
&lt;li&gt;The server may not allow CORS.&lt;/li&gt;
&lt;li&gt;Some media segments may be blocked.&lt;/li&gt;
&lt;li&gt;The stream may use unsupported codecs.&lt;/li&gt;
&lt;li&gt;The page may be using HTTPS while the stream uses HTTP.&lt;/li&gt;
&lt;li&gt;The stream may require authorization.&lt;/li&gt;
&lt;li&gt;The URL may have expired.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if the tool cannot know the exact reason every time, giving practical hints makes the debugging process much easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I started collecting these notes
&lt;/h2&gt;

&lt;p&gt;I started organizing M3U8 and HLS-related notes here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/flbdennis/m3u8player" rel="noopener noreferrer"&gt;https://github.com/flbdennis/m3u8player&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not meant to be a complex player framework.&lt;/p&gt;

&lt;p&gt;It is more like a practical place for M3U8-related notes, explanations, and useful technical content.&lt;/p&gt;

&lt;p&gt;For developers who are new to HLS, this kind of simple and practical explanation can sometimes be more useful than jumping straight into API documentation.&lt;/p&gt;

&lt;p&gt;Sometimes the real question is not “which player should I use?”&lt;/p&gt;

&lt;p&gt;The real question is:&lt;/p&gt;

&lt;p&gt;“Why does this M3U8 URL not play in my browser?”&lt;/p&gt;

&lt;h2&gt;
  
  
  A related playback testing project
&lt;/h2&gt;

&lt;p&gt;I also have another project related to browser-based video playback testing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/flbdennis/player-tools" rel="noopener noreferrer"&gt;https://github.com/flbdennis/player-tools&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This project is more focused on testing playback behavior in the browser.&lt;/p&gt;

&lt;p&gt;The way I think about the two projects is simple:&lt;/p&gt;

&lt;p&gt;The M3U8 notes project is for explanations and practical writing.&lt;/p&gt;

&lt;p&gt;The playback tools project is for testing video URLs in the browser.&lt;/p&gt;

&lt;p&gt;They are related, but they are not the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;M3U8 playback looks simple from the outside, but there are many small details behind it.&lt;/p&gt;

&lt;p&gt;The browser, playlist, media segments, server headers, CORS, HTTPS, codecs, and authorization rules all matter.&lt;/p&gt;

&lt;p&gt;If you are working with M3U8 or HLS, it helps to debug the whole playback chain instead of only looking at the player.&lt;/p&gt;

&lt;p&gt;Start with simple checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can the playlist load?&lt;/li&gt;
&lt;li&gt;Can the segments load?&lt;/li&gt;
&lt;li&gt;Does CORS allow the request?&lt;/li&gt;
&lt;li&gt;Is HTTPS correct?&lt;/li&gt;
&lt;li&gt;Are the codecs supported?&lt;/li&gt;
&lt;li&gt;Does the stream need authorization?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These basic questions can save a lot of time.&lt;/p&gt;

&lt;p&gt;For me, the main lesson is simple: an M3U8 player is only one part of the whole playback process. To understand playback issues, you need to look at the full path from the browser to the playlist and then to the media segments.&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>video</category>
      <category>frontend</category>
    </item>
    <item>
      <title>M3U8</title>
      <dc:creator>Dennis Fan</dc:creator>
      <pubDate>Sat, 06 Jun 2026 09:00:05 +0000</pubDate>
      <link>https://dev.to/flbdennis/m3u8-1k7p</link>
      <guid>https://dev.to/flbdennis/m3u8-1k7p</guid>
      <description></description>
    </item>
  </channel>
</rss>
