secured m3u8 can't play with Roku but with VLC

Why Roku doesn’t support secured m3u8 link? I am able to play this in VLC fine.
example…

http://*****_*********_hl-lh.akamaihd.net/i/**_****_hls_1@175738/master.m3u8?hdnea=st=1410478550~exp=1410514550~acl=/*~hmac=7ed6be672a3df528f55369b0b90b076736cce98cd2d886592f6f69133352507f&play-only=backup&jwstreamtype=hls

That isn’t enough information to let anyone help you troubleshoot. How are you setting up playback of the URL? Did you set the stream format to “hls”?

  • Joel

no I do not set the stream. I grab the stream link from other public site. I want to add this m3u8 stream to XML stream to play on Roku.

Again, more information needed for anyone to help you here, I suggest writing longer sentences and including some excerpts from your Brightscript code, and also your XML to show what you are doing so people can help you. If there is anything specifically you don’t want to share publicly then obscure that part of the code like you did in your first post.

  • Joel

I am using roku SDK template. I was able to successfully able to play regular m3u8 streams on my roku via this videoplayer app.

but when I try to play this secured m3u8 stream in roku it doesn’t recognize it, but it works fine in VLC player.

Here is XML code.


<item sdImg="http://www.ddpunjabi.in/images/logo%20new2.png" hdImg="http://www.ddpunjabi.in/images/logo%20new2.png">
		<title>Test Channel</title>
		<contentId>98200</contentId>
		<contentType>MUSIC</contentType>
		<contentQuality>HD</contentQuality>
		<streamFormat>hls</streamFormat>
		<media>
			<streamQuality>HD</streamQuality>
			<streamBitrate>1500</streamBitrate>
			<streamUrl>http://*****_*********_hl-lh.akamaihd.net/i/**_****_hls_1@175738/master.m3u8?hdnea=st=1410478550~exp=1410514550~acl=/*~hmac=7ed6be672a3df528f55369b0b90b076736cce98cd2d886592f6f69133352507f&play-only=backup&jwstreamtype=hls</streamUrl>
		</media>
		<synopsis>Test</synopsis>
		<genres>EDU</genres>
		<runtime>11260</runtime>
	</item>

“zuber” wrote:
I am using roku SDK template. I was able to successfully able to play regular m3u8 streams on my roku via this videoplayer app.

but when I try to play this secured m3u8 stream in roku it doesn’t recognize it, but it works fine in VLC player.

Here is XML code.



You haven’t XML encoded the URL there, so the ampersands are almost certainly causing the parsing of the XML to fail. Run the XML through an XML validator like this one: http://www.w3schools.com/xml/xml_validator.asp

Sorry, is this what you meant?


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<feed>
	<!-- resultLength indicates the total number of results for this feed -->
	<resultLength>3</resultLength>
	<!-- endIndex  indicates the number of results for this *paged* section of the feed -->
	<endIndex>3</endIndex>
<item sdImg="http://www.ddpunjabi.in/images/logo%20new2.png" hdImg="http://www.ddpunjabi.in/images/logo%20new2.png">
      <title>Test Channel</title>
      <contentId>98200</contentId>
      <contentType>MUSIC</contentType>
      <contentQuality>HD</contentQuality>
      <streamFormat>hls</streamFormat>
      <media>
         <streamQuality>HD</streamQuality>
         <streamBitrate>1500</streamBitrate>
         <streamUrl>http://*****_*********_hl-lh.akamaihd.net/i/**_****_hls_1@175738/master.m3u8?hdnea=st=1410478550~exp=1410514550~acl=/*~hmac=7ed6be672a3df528f55369b0b90b076736cce98cd2d886592f6f69133352507f&play-only=backup&jwstreamtype=hls</streamUrl>
      </media>
      <synopsis>Test</synopsis>
      <genres>EDU</genres>
      <runtime>11260</runtime>
   </item>
</feed>

This line in your XML:

<streamUrl>http://*****_*********_hl-lh.akamaihd.net/i/**_****_hls_1@175738/master.m3u8?hdnea=st=1410478550~exp=1410514550~acl=/*~hmac=7ed6be672a3df528f55369b0b90b076736cce98cd2d886592f6f69133352507f&play-only=backup&jwstreamtype=hls</streamUrl>

should be:

<streamUrl>http://*****_*********_hl-lh.akamaihd.net/i/**_****_hls_1@175738/master.m3u8?hdnea=st=1410478550~exp=1410514550~acl=/*~hmac=7ed6be672a3df528f55369b0b90b076736cce98cd2d886592f6f69133352507f&play-only=backup&jwstreamtype=hls</streamUrl>

You are Genius ma.. can you please explain why it works this by adding amp; please ?

also if I can set aspect ratio to stretch or 16:9.

Thanks again

“zuber” wrote:
You are Genius ma.. can you please explain why it works this by adding amp; please ?

also if I can set aspect ratio to stretch or 16:9.

Thanks again
The ampersand (&) is a reserved character in XML, so anytime it’s used in a value (barring CDATA, but that’s a different topic) it has to be encoded as &. Here’s a blog post that does a decent job explaining it: http://www.microshell.com/programming/p … ampersand/

As for changing the aspect ratio, I’m afraid that’s not possible. It’d certainly be nice, but either the chipset doesn’t support it, or Roku decided not to expose it for some reason.

Thanks a lot for your help and link.

See http://sdkdocs.roku.com/display/sdkdoc/ … deasString for a useful utility function and a list of the characters you should be concerned about. Inside xml element content or attribute value, they should be escaped to so-called “character entity references”.

BrightScript Debugger> ? "escaped chars: < ' & >".getEntityEncode()
escaped chars: < ' & >

Not all video streams that can play on VLC or other media players are able to play on Roku devices. To make sure the stream is Roku-compatible, try running it using this code, which will play a single video and generate debug logs for any errors and system log messages to help you diagnose if/why it won’t play. Substitute your video url for the one in this sample code.


Function _DEBUG_ON () As Boolean : Return True : End Function    ' Return True => Debugging ON

Sub Main ()
    port = CreateObject ("roMessagePort")

    ' Use roSystemLog to log system events
    sl = CreateObject ("roSystemLog")
    sl.SetMessagePort (port)
    sl.EnableType ("http.error")
    sl.EnableType ("http.connect")
    sl.EnableType ("bandwidth.minute")

    ' Use roVideoScreen to play the video
    ui = CreateObject ("roVideoScreen")
    ui.SetMessagePort (port)
    ui.SetCertificatesFile ("common:/certs/ca-bundle.crt")      ' Required for "https" urls
    ui.SetContent ({
                    StreamFormat: "hls",    ' "hls or "mp4"
                    Stream: {
                                Url:        "http://iphone-streaming.ustream.tv/ustreamVideo/1524/streams/live/playlist.m3u8"
                                Bitrate:    0
                                Quality:    False      ' At least one SD stream is required if using an SD TV
                            }
                    })
    ui.Show ()

    ' Event loop
    While True
        msg = Wait (0, port)
        _logEvent ("Main", msg)
    End While

End Sub

'
' Log events
'
Function _logEvent (proc As String, msg As Dynamic) As Void
    If _DEBUG_ON ()
        If msg = Invalid
            evType = "Invalid"
            _debug (proc + ". Invalid")
        Else
            evStr = ""
            evType = Type (msg)
            If evType = "roVideoScreenEvent" Or evType = "roVideoPlayerEvent"
                msgType = msg.GetType ().ToStr ()
                If msg.IsStreamStarted ()
                    info = msg.GetInfo ()
                    If info.IsUnderrun Then underrun = "true" Else underrun = "false"
                    evStr = "isStreamStarted. Index: " + msg.GetIndex ().ToStr ()
                    evStr = evStr + ". Url: " + info.Url
                    evStr = evStr + ". StreamBitrate: " + StrI (info.StreamBitrate / 1000).Trim ()
                    evStr = evStr + ". MeasuredBitrate: " + info.MeasuredBitrate.ToStr ()
                    evStr = evStr + ". IsUnderrun: " + underrun
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsPlaybackPosition ()
                    evStr = "isPlaybackPosition. Index: " + msg.GetIndex ().ToStr ()
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsRequestFailed ()
                    index = msg.GetIndex ()
                    info = msg.GetInfo ()
                    evStr = "isRequestFailed. Message: " + msg.GetMessage () + " Index: " + index.ToStr ()
                    If index <= 0 And index >= -5
                        failMessage = [ "Network error : server down or unresponsive, server is unreachable, network setup problem on the client",
                                        "HTTP error: malformed headers or HTTP error result",
                                        "Connection timed out",
                                        "Unknown error",
                                        "Empty list; no streams were specified to play",
                                        "Media error; the media format is unknown or unsupported" ][-index]
                        evStr = evStr + " [" + failMessage + "]"
                    End If
                    If info.LookupCI ("Url") <> Invalid Then evStr = evStr + ". Url: " + info.Url
                    If info.LookupCI ("StreamBitrate") <> Invalid Then evStr = evStr + ". StreamBitrate: " + info.StreamBitrate.ToStr ()
                    If info.LookupCI ("MeasuredBitrate") <> Invalid Then evStr = evStr + ". MeasuredBitrate: " + info.MeasuredBitrate.ToStr ()
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsStatusMessage ()
                    evStr = "isStatusMessage. Message: " + msg.GetMessage ()
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsFullResult ()
                    evStr = "isFullResult"
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsPartialResult ()
                    evStr = "isPartialResult"
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsPaused ()
                    evStr = "isPaused"
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsResumed ()
                    evStr = "isResumed"
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsScreenClosed ()
                    evStr = "isScreenClosed"
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else If msg.IsStreamSegmentInfo ()
                    info = msg.GetInfo ()
                    evStr = "isStreamSegmentInfo. Message: " + msg.GetMessage () + ". Index: " + msg.GetIndex ().ToStr ()
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                    _debug ("StreamBandwidth:  " + info.StreamBandwidth.ToStr (), ">     ")
                    _debug ("Sequence:         " + info.Sequence.ToStr (), ">     ")
                    _debug ("SegUrl:           " + info.SegUrl, ">     ")
                    _debug ("SegStartTime:     " + info.SegStartTime.ToStr (), ">     ")
                Else If msg.IsDownloadSegmentInfo ()    ' Undocumented event
                    info = msg.GetInfo ()
                    evStr = "isDownloadSegmentInfo. Message: " + msg.GetMessage () + ". Index: " + msg.GetIndex ().ToStr ()
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                    _debug ("Sequence:         " + info.Sequence.ToStr (), ">     ")
                    _debug ("Status:           " + info.Status.ToStr (), ">     ")
                    _debug ("SegBitrate:       " + info.SegBitrate.ToStr (), ">     ")
                    _debug ("DownloadDuration: " + info.DownloadDuration.ToStr (), ">     ")
                    _debug ("SegUrl:           " + info.SegUrl, ">     ")
                    _debug ("SegSize:          " + info.SegSize.ToStr (), ">     ")
                    _debug ("BufferSize:       " + info.BufferSize.ToStr (), ">     ")
                    _debug ("BufferLevel:      " + info.BufferLevel.ToStr (), ">     ")
                    _debug ("SegType:          " + info.SegType.ToStr (), ">     ")
                Else If msg.IsListItemSelected ()       ' Undocumented event for this event type
                    evStr = "isListItemSelected ???. Index: " + msg.GetIndex ().ToStr ()
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                Else
                    evStr = "Unknown. Message: " + msg.GetMessage () + " Index: " + msg.GetIndex ().ToStr ()
                    _debug (proc + ". " + evType + " [" + msgType + "]-" + evStr)
                End If
            Else If evType = "roSystemLogEvent"
                msgType = msg.GetType ().ToStr ()
                info = msg.GetInfo ()
                _debug (proc + ". " + evType + " [" + msgType + "]-" + "LogType=" + info.LogType + ". Datetime: " + _timeStr (info.Datetime))
                evStr = ""
                If info.LogType = "http.error" Or info.LogType = "http.connect"
                    _debug ("Url:              " + info.Url, ">     ")
                    _debug ("Status:           " + info.Status, ">     ")
                    _debug ("HttpCode:         " + info.HttpCode.ToStr (), ">     ")
                    _debug ("Method:           " + info.Method, ">     ")
                    _debug ("TargetIp:         " + info.TargetIp, ">     ")
                    _debug ("OrigUrl:          " + info.OrigUrl, ">     ")
                Else If info.LogType = "bandwidth.minute"
                    _debug ("Bandwidth: " + info.bandwidth.ToStr (), ">     ")
                Else
                    ' Unknown log type
                    _debug ("(unknown log type)", ">     ")
                End If
            '
            ' Add more event types here as needed ...
            '
            
            Else
                _debug (proc + ". Unexpected Event: " + evType)
            End If
        End If
    End If
End Function

Function _timeStr (dtIn = Invalid As Object) As String

    dt = CreateObject ("roDateTime")

    If dtIn = Invalid
        dt.Mark ()
    Else
        dt = dtIn
    End If
    
    dt.ToLocalTime ()

    str = ""
    str = str + Right ("0" + dt.GetHours ().ToStr (), 2)            + ":"   
    str = str + Right ("0" + dt.GetMinutes ().ToStr (), 2)          + ":"
    str = str + Right ("0" + dt.GetSeconds ().ToStr (), 2)          + "."
    str = str + Right ("00" + dt.GetMilliseconds ().ToStr (), 3)    + "   "
    
    Return str
    
End Function

'
' Log _debug messages to the console. See _DEBUG () at the start of the code
'
Sub _debug (message As String, indentString = "" As String)
    If _DEBUG_ON ()
        dt = CreateObject ("roDateTime")
        dt.ToLocalTime ()
        hh  = Right ("0" + dt.GetHours ().ToStr (), 2)
        mm  = Right ("0" + dt.GetMinutes ().ToStr (), 2)
        ss  = Right ("0" + dt.GetSeconds ().ToStr (), 2)
        mmm = Right ("00" + dt.GetMilliseconds ().ToStr (), 3)
        Print hh; ":"; mm; ":"; ss; "."; mmm; "  "; indentString; message
    End If
End Sub