Skip links
blog-hero-right-bg
How to video stream of IPTV with m3u8 parser in Swift
Medium

How to video stream of IPTV with m3u8 parser in Swift

We all know building an iOS application requires some UI and Swift knowledge. While creating...

Burak Atmaca , Content Specialist

Average Reading Time 4 min

M3U File

m3u is a computer file format for a multimedia playlist. m3u8 includes album artisttrack informationdisplay title, etc…

#EXTM3U
#EXTINF:0, TRT1
https://tv-trt1.medya.trt.com.tr/master_720.m3u8
#EXTINF:0, TRT 1 HD
https://mn-nl.mncdn.com/blutv_trt12/live.m3u8
#EXTINF:0, TRT 1 FHD
http://213.115.248.46:9000/TR_-_TRT_1_HD_PLUS/index.m3u8
#EXTINF:0, ATV SD
http://azerbaijan1.livetv.az/turkey/atv_turk_sd/playlist.m3u8
#EXTINF:0, ATV HD TR
https://trkvz-live.daioncdn.net/atv/atv_720p.m3u8
#EXTINF:0, ATV FHD
http://213.115.248.46:9000/TR_-_ATV_HD_PLUS/index.m3u8

Parser Logic

//
// m3u8Parse.swift
// M3U8ParseTutorial
//
// Created by Abdullah Yalçın on 6.07.2022.
//
import Foundation
struct MediaItem: Codable {
var duration: Int?
var title: String?
var urlString: String?
}
class ParseHelper {
func parseM3U(contentsOfFile: String) -> [MediaItem] {
var mediaItems = [MediaItem]()
contentsOfFile.enumerateLines(invoking: { line, stop in
if line.hasPrefix(#EXTINF:) {
let infoLine = line.replacingOccurrences(of: #EXTINF:, with: )
let infos = Array(infoLine.components(separatedBy: ,))
if let durationString = infos.first, let duration = Int(durationString) {
let mediaItem = MediaItem(duration: duration, title: infos.last?.trimmingCharacters(in: .whitespaces), urlString: nil)
mediaItems.append(mediaItem)
}
} else {
if mediaItems.count > 0 {
mediaItems[mediaItems.count 1].urlString = line
}
}
})
return mediaItems
}
}
  • #EXTINF:“ word defines a playlist fileIt looks up line by line, then maps into MediaItem.

ViewController to stream

//
// IPTVViewController.swift
// avemobilecms
//
// Created by Abdullah Yalçın on 6.07.2022.
//
import Foundation
import AVKit
class IPTVViewController: UIViewController {
@IBOutlet private weak var listTableView: UITableView!
private var mediaList: [MediaItem] = []
private let m3uFileLink = myUrl.cdn.net/example.m3u
override func viewDidLoad() {
super.viewDidLoad()
if let url = URL(string: m3uFileLink) {
do {
let fileContents = try String(contentsOf: url, encoding: .ascii)
mediaList = ParseHelper().parseM3U(contentsOfFile: fileContents)
listTableView.register(UITableViewCell.self, forCellReuseIdentifier: UITableViewCell.reuseIdentifier)
listTableView.delegate = self
listTableView.dataSource = self
}catch {
print(error)
}
}
}
private func executeUrl(row: Int) {
if let urlString = mediaList[row].urlString, let url = URL(string: urlString) {
let player = AVPlayer(url: url)
let controller = AVPlayerViewController()
controller.delegate = self
controller.player = player
present(controller, animated: true) {
player.play()
}
}
}
}
extension IPTVViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
mediaList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: UITableViewCell.reuseIdentifier, for: indexPath)
cell.textLabel?.text = mediaList[indexPath.row].title
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
executeUrl(row: indexPath.row)
}
}
extension IPTVViewController: AVPlayerViewControllerDelegate {
func playerViewController(_ playerViewController: AVPlayerViewController, failedToStartPictureInPictureWithError error: Error) {
print(error)
}
func playerViewController(_ playerViewController: AVPlayerViewController,
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
present(playerViewController, animated: false) {
completionHandler(true)
}
}
}
  • Build a listTableView to present media.
  • AVKit can get a stream URL directly, which is built-in.
  • AVPlayerViewControllerDelegate is used for Picture-in-Picture option.

In order to activate Picture-in-Picture in your app

  • Enable “Audio, Airplay, and Picture in Picture” mode in your app target.
  • In your appDelegate -> didFinishLaunchingWithOptions function, set category and activate like below.

article-cloud-right