Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
brainfood
/
videojs-contrib-hls
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
eda08662
authored
2013-10-24 16:28:47 -0400
by
Tom Johnson
Committed by
David LaPalomento
2013-10-24 14:17:58 -0700
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
toms working example base
1 parent
3b271282
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
207 additions
and
96 deletions
example.html
src/hls-playback-controller.js
src/m3u8/m3u8-parser.js
src/m3u8/m3u8.js
src/manifest-controller.js
src/segment-controller.js
test/video-js-hls_test.js
example.html
View file @
eda0866
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
>
<title>
video.js HLS Plugin Example
</title>
<meta
charset=
"utf-8"
>
<title>
video.js HLS Plugin Example
</title>
<link
href=
"node_modules/video.js/video-js.css"
rel=
"stylesheet"
>
...
...
@@ -25,9 +25,11 @@
<!-- m3u8 handling -->
<script
src=
"src/m3u8/m3u8.js"
></script>
<script
src=
"src/m3u8/m3u8-parser.js"
></script>
<script
src=
"src/m3u8/m3u8-tag-types.js"
></script>
<script
src=
"src/m3u8/m3u8-parser.js"
></script>
<script
src=
"src/manifest-controller.js"
></script>
<script
src=
"src/segment-controller.js"
></script>
<script
src=
"src/hls-playback-controller.js"
></script>
<!-- example MPEG2-TS segments -->
<!-- bipbop -->
...
...
@@ -48,51 +50,12 @@
// initialize the player
videojs
.
options
.
flash
.
swf
=
'node_modules/videojs-media-sources/video-js-with-mse.swf'
;
video
=
videojs
(
'video'
);
// create a media source
mediaSource
=
new
videojs
.
MediaSource
();
mediaSource
.
addEventListener
(
'sourceopen'
,
function
(
event
){
var
parser
=
new
videojs
.
hls
.
SegmentParser
(),
sourceBuffer
=
mediaSource
.
addSourceBuffer
(
'video/flv; codecs="vp6,aac"'
);
everything
=
[];
// feed parsed bytes into the player
everything
.
push
(
parser
.
getFlvHeader
());
sourceBuffer
.
appendBuffer
(
everything
[
everything
.
length
-
1
],
video
);
parser
.
parseSegmentBinaryData
(
window
.
bcSegment
);
while
(
parser
.
tagsAvailable
())
{
everything
.
push
(
parser
.
getNextTag
().
bytes
);
sourceBuffer
.
appendBuffer
(
everything
[
everything
.
length
-
1
],
video
);
}
parser
.
flushTags
();
while
(
parser
.
tagsAvailable
())
{
everything
.
push
(
parser
.
getNextTag
().
bytes
);
sourceBuffer
.
appendBuffer
(
everything
[
everything
.
length
-
1
],
video
);
}
var
iframe
=
document
.
createElement
(
'iframe'
);
iframe
.
src
=
'data:video/x-flv;base64,'
+
window
.
btoa
((
Array
.
prototype
.
map
.
call
(
everything
.
reduce
(
function
(
result
,
next
)
{
var
array
=
new
Uint8Array
(
result
.
byteLength
+
next
.
byteLength
);
array
.
set
(
result
);
array
.
set
(
next
,
result
.
length
);
return
array
;
}),
function
(
byte
)
{
return
String
.
fromCharCode
(
byte
);
})).
join
(
''
));
//console.log(iframe);
// document.body.appendChild(iframe);
},
false
);
url
=
videojs
.
URL
.
createObjectURL
(
mediaSource
);
video
.
src
({
src
:
url
,
type
:
"video/flv"
video
=
videojs
(
'video'
,{},
function
(){
this
.
playbackController
=
new
window
.
videojs
.
hls
.
HLSPlaybackController
(
this
);
this
.
playbackController
.
loadManifest
(
"http://localhost:7070/test/basic-playback/zencoder/gogo/manifest.m3u8"
,
function
(
data
){
console
.
log
(
data
)});
});
</script>
</body>
</html>
...
...
src/hls-playback-controller.js
0 → 100644
View file @
eda0866
(
function
(
window
)
{
window
.
videojs
.
hls
.
HLSPlaybackController
=
function
(
vjsPlayerReference
)
{
var
ManifestController
=
window
.
videojs
.
hls
.
ManifestController
;
var
SegmentController
=
window
.
videojs
.
hls
.
SegmentController
;
var
MediaSource
=
window
.
videojs
.
MediaSource
;
var
SegmentParser
=
window
.
videojs
.
hls
.
SegmentParser
;
var
M3U8
=
window
.
videojs
.
hls
.
M3U8
;
var
self
=
this
;
self
.
player
=
vjsPlayerReference
;
self
.
mediaSource
=
new
MediaSource
();
self
.
parser
=
new
SegmentParser
();
self
.
manifestController
=
null
;
self
.
segmentController
=
null
;
self
.
manifestLoaded
=
false
;
self
.
currentSegment
=
0
;
self
.
currentManifest
=
null
;
self
.
currentPlaylist
=
null
;
self
.
currentRendition
=
null
;
// Register Externall Callbacks
self
.
manifestLoadCompleteCallback
;
self
.
player
.
on
(
'timeupdate'
,
function
()
{
console
.
log
(
self
.
player
.
currentTime
());
});
self
.
player
.
on
(
'onsrcchange'
,
function
()
{
console
.
log
(
'src change'
,
self
.
player
.
currentSrc
());
//if src.url.m3u8 -- loadManifest.url
});
self
.
rendition
=
function
(
rendition
)
{
self
.
currentRendition
=
rendition
;
self
.
loadManifest
(
self
.
currentRendition
.
url
,
self
.
onM3U8LoadComplete
,
self
.
onM3U8LoadError
,
self
.
onM3U8Update
);
};
self
.
loadManifest
=
function
(
manifestUrl
,
onDataCallback
,
onErrorCallback
,
onUpdateCallback
)
{
self
.
mediaSource
.
addEventListener
(
'sourceopen'
,
function
(
event
)
{
console
.
log
(
'source open here'
);
// feed parsed bytes into the player
self
.
sourceBuffer
=
self
.
mediaSource
.
addSourceBuffer
(
'video/flv; codecs="vp6,aac"'
);
self
.
parser
=
new
SegmentParser
();
self
.
sourceBuffer
.
appendBuffer
(
self
.
parser
.
getFlvHeader
(),
video
);
if
(
onDataCallback
)
{
self
.
manifestLoadCompleteCallback
=
onDataCallback
;
}
self
.
manifestController
=
new
ManifestController
();
self
.
manifestController
.
loadManifest
(
manifestUrl
,
self
.
onM3U8LoadComplete
,
self
.
onM3U8LoadError
,
self
.
onM3U8Update
);
},
false
);
self
.
player
.
src
({
src
:
videojs
.
URL
.
createObjectURL
(
self
.
mediaSource
),
type
:
"video/flv"
});
};
self
.
onM3U8LoadComplete
=
function
(
m3u8
)
{
if
(
m3u8
.
invalidReasons
.
length
==
0
)
{
if
(
m3u8
.
isPlaylist
)
{
self
.
currentPlaylist
=
m3u8
;
self
.
rendition
(
self
.
currentPlaylist
.
playlistItems
[
0
]);
}
else
{
self
.
currentManifest
=
m3u8
;
self
.
manifestLoaded
=
true
;
self
.
loadSegment
(
self
.
currentManifest
.
mediaItems
[
0
]);
if
(
self
.
manifestLoadCompleteCallback
)
{
self
.
manifestLoadCompleteCallback
(
m3u8
);
}
}
}
};
self
.
onM3U8LoadError
=
function
(
error
)
{
};
self
.
onM3U8Update
=
function
(
m3u8
)
{
};
self
.
loadSegment
=
function
(
segment
)
{
self
.
segmentController
=
new
SegmentController
();
self
.
segmentController
.
loadSegment
(
segment
.
url
,
self
.
onSegmentLoadComplete
,
self
.
onSegmentLoadError
);
};
self
.
onSegmentLoadComplete
=
function
(
segment
)
{
self
.
parser
.
parseSegmentBinaryData
(
segment
.
binaryData
);
while
(
self
.
parser
.
tagsAvailable
())
{
self
.
sourceBuffer
.
appendBuffer
(
self
.
parser
.
getNextTag
().
bytes
,
self
.
player
);
};
console
.
log
(
'load another'
,
self
.
currentSegment
,
self
.
currentManifest
.
mediaItems
.
length
);
if
(
self
.
currentSegment
<
self
.
currentManifest
.
mediaItems
.
length
-
1
)
{
console
.
log
(
'load another'
);
self
.
loadNextSegment
();
}
};
self
.
loadNextSegment
=
function
()
{
self
.
currentSegment
++
;
self
.
loadSegment
(
self
.
currentManifest
.
mediaItems
[
self
.
currentSegment
]);
}
self
.
onSegmentLoadError
=
function
(
error
)
{
};
};
})(
this
);
\ No newline at end of file
src/m3u8/m3u8-parser.js
View file @
eda0866
...
...
@@ -4,6 +4,8 @@
window
.
videojs
.
hls
.
M3U8Parser
=
function
()
{
var
self
=
this
;
self
.
directory
;
var
tagTypes
=
window
.
videojs
.
hls
.
m3u8TagType
;
var
lines
=
[];
var
data
;
...
...
@@ -31,6 +33,11 @@
self
.
parse
=
function
(
rawDataString
)
{
data
=
new
M3U8
();
if
(
self
.
directory
)
{
data
.
directory
=
self
.
directory
;
}
if
(
rawDataString
!=
undefined
&&
rawDataString
.
toString
().
length
>
0
)
{
lines
=
rawDataString
.
split
(
'\n'
);
...
...
@@ -72,6 +79,15 @@
segment
.
url
=
lines
[
index
+
1
];
}
if
(
segment
.
url
.
indexOf
(
"http"
)
===-
1
&&
self
.
directory
)
{
if
(
data
.
directory
[
data
.
directory
.
length
-
1
]
===
segment
.
url
[
0
]
&&
segment
.
url
[
0
]
===
"/"
)
{
segment
.
url
=
segment
.
url
.
substr
(
1
);
}
segment
.
url
=
self
.
directory
+
segment
.
url
;
}
data
.
mediaItems
.
push
(
segment
);
break
;
...
...
@@ -116,7 +132,7 @@
break
;
case
tagTypes
.
ZEN_TOTAL_DURATION
:
data
.
totalDuration
=
self
.
getTagValue
(
value
);
data
.
totalDuration
=
Number
(
self
.
getTagValue
(
value
)
);
break
;
case
tagTypes
.
VERSION
:
...
...
src/m3u8/m3u8.js
View file @
eda0866
(
function
(
window
)
{
window
.
videojs
.
hls
.
M3U8
=
function
()
{
this
.
directory
=
""
;
this
.
allowCache
=
"NO"
;
this
.
playlistItems
=
[];
this
.
mediaItems
=
[];
...
...
src/manifest-controller.js
View file @
eda0866
(
function
(
window
)
{
(
function
(
window
)
{
var
M3U8
=
window
.
videojs
.
hls
.
M3U8
;
var
M3U8Parser
=
window
.
videojs
.
hls
.
M3U8Parser
;
window
.
videojs
.
hls
.
ManifestController
=
function
(){
window
.
videojs
.
hls
.
ManifestController
=
function
()
{
var
self
=
this
;
var
parser
;
var
data
;
var
onDataCallback
;
var
onErrorCallback
;
var
onUpdateCallback
;
self
.
parser
;
self
.
data
;
self
.
url
;
self
.
onDataCallback
;
self
.
onErrorCallback
;
self
.
onUpdateCallback
;
self
.
loadManifest
=
function
(
manifestUrl
,
onDataCallback
,
onErrorCallback
,
onUpdateCallback
)
{
self
.
url
=
manifestUrl
;
self
.
loadManifest
=
function
(
manifestUrl
,
onDataCallback
,
onErrorCallback
,
onUpdateCallback
)
{
self
.
onDataCallback
=
onDataCallback
;
self
.
onErrorCallback
=
onErrorCallback
;
self
.
onUpdateCallback
=
onUpdateCallback
;
if
(
onDataCallback
)
{
self
.
onDataCallback
=
onDataCallback
;
}
if
(
onErrorCallback
)
{
self
.
onErrorCallback
=
onErrorCallback
;
}
if
(
onUpdateCallback
)
{
self
.
onUpdateCallback
=
onUpdateCallback
;
}
vjs
.
get
(
manifestUrl
,
self
.
onManifestLoadComplete
,
self
.
onManifestLoadError
);
};
self
.
parseManifest
=
function
(
dataAsString
)
{
self
.
parseManifest
=
function
(
dataAsString
)
{
self
.
parser
=
new
M3U8Parser
();
self
.
data
=
self
.
parser
.
parse
(
dataAsString
);
self
.
parser
.
directory
=
/^
(\/?
|
)([\s\S]
*
?)((?:\.{1,2}
|
[^\/]
+
?
|
)(\.[^
.
\/]
*|
))(?:[\/]
*
)
$/
.
exec
(
self
.
url
).
slice
(
1
)[
1
];
self
.
data
=
self
.
parser
.
parse
(
dataAsString
);
return
self
.
data
;
};
self
.
onManifestLoadComplete
=
function
(
response
)
{
self
.
onManifestLoadComplete
=
function
(
response
)
{
var
output
=
self
.
parseManifest
(
response
);
if
(
self
.
onDataCallback
!=
undefined
)
{
if
(
self
.
onDataCallback
!=
undefined
)
{
self
.
onDataCallback
(
output
);
}
};
self
.
onManifestLoadError
=
function
(
err
)
{
if
(
err
)
{
console
.
log
(
err
.
message
);
}
if
(
self
.
onErrorCallback
!=
undefined
)
{
onErrorCallback
((
err
!=
undefined
)
?
err
:
null
);
self
.
onManifestLoadError
=
function
(
err
)
{
if
(
self
.
onErrorCallback
!=
undefined
)
{
self
.
onErrorCallback
((
err
!=
undefined
)
?
err
:
null
);
}
};
}
...
...
src/segment-controller.js
View file @
eda0866
(
function
(
window
)
{
var
SegmentParser
=
window
.
videojs
.
hls
.
SegmentParser
;
window
.
videojs
.
hls
.
SegmentController
=
function
(){
var
self
=
this
;
var
url
;
var
parser
;
var
requestTimestamp
;
var
responseTimestamp
;
var
data
;
var
onDataCallback
;
var
onErrorCallback
;
var
onUpdateCallback
;
self
.
url
;
self
.
requestTimestamp
;
self
.
responseTimestamp
;
self
.
data
;
self
.
onDataCallback
;
self
.
onErrorCallback
;
self
.
onUpdateCallback
;
self
.
loadSegment
=
function
(
segmentUrl
,
onDataCallback
,
onErrorCallback
,
onUpdateCallback
)
{
self
.
url
=
segmentUrl
;
...
...
@@ -22,29 +21,31 @@
self
.
onUpdateCallback
=
onUpdateCallback
;
self
.
requestTimestamp
=
new
Date
().
getTime
();
var
req
=
new
XMLHttpRequest
();
req
.
open
(
'GET'
,
segmentUrl
,
true
);
req
.
responseType
=
'arraybuffer'
;
req
.
onload
=
function
(
response
)
{
self
.
onSegmentLoadComplete
(
new
Uint8Array
(
req
.
response
));
};
req
.
send
(
null
);
var
req
=
new
XMLHttpRequest
();
req
.
open
(
'GET'
,
segmentUrl
,
true
);
req
.
responseType
=
'arraybuffer'
;
req
.
onload
=
function
(
response
)
{
self
.
onSegmentLoadComplete
(
new
Uint8Array
(
req
.
response
));
};
req
.
send
(
null
);
//vjs.get(segmentUrl, self.onSegmentLoadComplete, self.onSegmentLoadError);
};
self
.
parseSegment
=
function
(
incomingData
)
{
// Add David's code later //
console
.
log
(
'got segment data'
,
incomingData
.
byteLength
);
self
.
data
=
{
whatever
:
incomingData
};
self
.
data
=
{};
self
.
data
.
binaryData
=
incomingData
;
self
.
data
.
url
=
self
.
url
;
self
.
data
.
isCached
=
false
;
self
.
data
.
requestTimestamp
=
self
.
requestTimestamp
;
self
.
data
.
responseTimestamp
=
self
.
responseTimestamp
;
self
.
data
.
byteLength
=
incomingData
.
byteLength
;
self
.
data
.
isCached
=
(
parseInt
(
self
.
responseTimestamp
-
self
.
requestTimestamp
)
<
75
);
self
.
data
.
throughput
=
self
.
calculateThroughput
(
self
.
data
.
byteLength
,
self
.
requestTimestamp
,
self
.
responseTimestamp
)
self
.
data
.
throughput
=
self
.
calculateThroughput
(
self
.
data
.
byteLength
,
self
.
requestTimestamp
,
self
.
responseTimestamp
)
;
return
self
.
data
;
};
...
...
test/video-js-hls_test.js
View file @
eda0866
This diff is collapsed.
Click to expand it.
Please
register
or
sign in
to post a comment