From 36887f565a7d336abf6bfda4f1fc9974173fcd70 Mon Sep 17 00:00:00 2001 From: Ilya Kreymer Date: Sat, 22 Nov 2014 18:39:30 -0800 Subject: [PATCH] video: more rewriting work, support: html audio if audio format, fallback to flash (flowplayer) if html video/audio playback has failed update setup.py to support nested include structure --- pywb/static/vidrw.js | 225 ++++++++++++++++++++++++++++++++------- pywb/ui/head_insert.html | 4 + setup.py | 3 +- 3 files changed, 194 insertions(+), 38 deletions(-) diff --git a/pywb/static/vidrw.js b/pywb/static/vidrw.js index 248d5373..9ce8478a 100644 --- a/pywb/static/vidrw.js +++ b/pywb/static/vidrw.js @@ -21,30 +21,80 @@ This file is part of pywb, https://github.com/ikreymer/pywb __wbvidrw = (function() { - var already_checked = false; + var found_embeds = false; function check_videos() { - if (already_checked) { + if (found_embeds) { return; } + var tags = []; + var iframes = document.getElementsByTagName("iframe"); for (var i = 0; i < iframes.length; i++) { - already_checked = true; - check_replacement(iframes[i], iframes[i].getAttribute("src")); + found_embeds = true; + tags.push([iframes[i], iframes[i].getAttribute("src")]); } var embeds = document.getElementsByTagName("embed"); for (var i = 0; i < embeds.length; i++) { - already_checked = true; - check_replacement(embeds[i], embeds[i].getAttribute("src")); + found_embeds = true; + tags.push([embeds[i], embeds[i].getAttribute("src")]); } - if (wbinfo.url.indexOf("://www.youtube.com/watch") > 0) { + var objects = document.getElementsByTagName("object"); + + for (var i = 0; i < objects.length; i++) { + var obj_url = undefined; + +/* if (is_watch_page(wbinfo.url)) { + check_replacement(objects[i], wbinfo.url); + console.log('IS WATCH'); + continue; + } +*/ + + for (var j = 0; j < objects[i].children.length; j++) { + var child = objects[i].children[j]; + + if (child.tagName == "EMBED") { + break; + } + + if (child.tagName == "PARAM") { + var name = child.getAttribute("name"); + name = name.toLowerCase(); + if (name == "flashvars") { + var value = child.getAttribute("value"); + value = decodeURIComponent(value); + var inx = value.indexOf("=http"); + if (inx >= 0) { + obj_url = value.substring(inx + 1); + console.log("OBJ URL: " + obj_url); + break; + } + } + } + } + + if (obj_url) { + continue; + } + + //check_replacement(objects[i], obj_url); + tags.push([objects[i], obj_url]); + } + + for (var i = 0; i < tags.length; i++) { + check_replacement(tags[i][0], tags[i][1]); + } + + // special case: yt + if (!found_embeds && wbinfo.url.indexOf("://www.youtube.com/watch") > 0) { var ytvideo = document.getElementsByTagName("video"); -/* + if (ytvideo.length == 1) { if (ytvideo[0].getAttribute("data-youtube-id") != "") { // Wait to see if video is playing, if so, don't replace it @@ -53,24 +103,31 @@ __wbvidrw = (function() { console.log("Replacing Broken Video"); check_replacement(ytvideo[0], wbinfo.url); } - }, 3000); + }, 4000); } } -*/ } } - function check_replacement(elem, src) { - if (!src) { - return; + function is_watch_page(url) { + if (url.indexOf("://www.dailymotion.com/") > 0) { + return true; } - if (src.indexOf("javascript:") == 0) { + return false; + } + + function check_replacement(elem, src) { + if (!src || src.indexOf("javascript:") == 0) { return; } src = _wb_wombat.extract_orig(src); + if (src.indexOf("dailymotion.com/swf/") > 0) { + src = src.replace("/swf/", "/video/"); + } + var xhr = new XMLHttpRequest(); xhr._no_rewrite = true; xhr.open('GET', wbinfo.prefix + 'vi_/' + src, true); @@ -82,13 +139,16 @@ __wbvidrw = (function() { xhr.send(); } - function do_replace_video(elem, video_info) { - // TODO: select based on size? - var video_url = video_info.url; - video_url = wbinfo.prefix + video_url; + function do_replace_video(elem, info) { + var video_url = video_url = wbinfo.prefix + info.url; + + var thumb_url = null; + + if (info.thumbnail) { + thumb_url = wbinfo.prefix + info.thumbnail; + } var tag = elem.tagName.toLowerCase(); - console.log("REPLACING: " + video_url); var width, height; @@ -100,26 +160,108 @@ __wbvidrw = (function() { height = elem.clientHeight; elem = elem.parentNode; - //elem.parentNode.setAttribute("id", "_wb_vid"); } else { width = elem.clientWidth; height = elem.clientHeight; } - console.log(video_info.ext); - // Try HTML5 Video var htmlvideo = document.createElement("video"); + var replacement = null; + + if (htmlvideo.canPlayType) { + if (can_play(htmlvideo, info.ext, "video/")) { + replacement = init_html_video(htmlvideo, width, height, video_url, thumb_url); + } else if (can_play(htmlvideo, info.ext, "audio/")) { + replacement = init_html_audio(video_url); + } else { + + var best_match_heur = 1000000; + var best_url = undefined; + + for (i = 0; i < info.formats.length; i++) { + if (can_play(htmlvideo, info.formats[i].ext)) { + + if ((Math.abs(width - info.formats[i].width) + Math.abs(height - info.formats[i].height)) < best_match_heur) { + best_url = info.formats[i].url; + console.log("ALT: " + info.formats[i].ext); + } + } + } + + if (best_url) { + video_url = wbinfo.prefix + best_url; + replacement = init_html_video(htmlvideo, width, height, video_url, thumb_url); + } + } + } + + var vidId = undefined; + + if (!replacement) { + replacement = document.createElement("div"); + + vidId = "_wb_vid" + Date.now(); + replacement.setAttribute("id", vidId); + } + + if (tag == "iframe") { + elem.parentNode.replaceChild(replacement, elem); + } else if (tag == "embed") { + if (elem.parentNode && elem.parentElement.tagName.toLowerCase() == "object") { + elem = elem.parentNode; + } + elem.parentNode.replaceChild(replacement, elem); + } else if (tag == "video") { + elem.parentNode.replaceChild(replacement, elem); + } + + if (vidId) { + init_flash_player(vidId, width, height, video_url, thumb_url); + } + } + + function can_play(elem, ext, type) { + if (!type) { + type = "video/"; + } + + var canplay = elem.canPlayType(type + ext); + if (canplay === "probably" || canplay === "maybe") { + return true; + } else { + return false; + } + } + + function init_html_audio(audio_url) { + var htmlaudio = document.createElement("audio"); + htmlaudio.setAttribute("src", audio_url); + htmlaudio.setAttribute("controls", "1"); + htmlaudio.style.backgroundColor = "#000"; + + htmlaudio.addEventListener("error", function() { + console.log("html5 audio error"); + }); + + htmlaudio.addEventListener("loadstart", function() { + console.log("html5 audio success"); + }); + + return htmlaudio; + } + + function init_html_video(htmlvideo, width, height, video_url, thumb_url) + { htmlvideo.setAttribute("src", video_url); htmlvideo.setAttribute("width", width); htmlvideo.setAttribute("height", height); htmlvideo.setAttribute("controls", "1"); htmlvideo.style.backgroundColor = "#000"; - if (video_info.thumbnail) { - var thumbnail = wbinfo.prefix + video_info.thumbnail; - htmlvideo.setAttribute("thumbnail", thumbnail); + if (thumb_url) { + htmlvideo.setAttribute("poster", thumb_url); } htmlvideo.addEventListener("error", function() { @@ -130,18 +272,27 @@ __wbvidrw = (function() { console.log("html5 video success"); }); - if (tag == "iframe") { - elem.parentNode.replaceChild(htmlvideo, elem); - } else if (tag == "embed") { - if (elem.parentNode && elem.parentElement.tagName.toLowerCase() == "object") { - elem = elem.parentNode; - } - elem.parentNode.replaceChild(htmlvideo, elem); - } else if (tag == "video") { - // elem = elem.parentNode; - // elem = elem.parentNode; - elem.parentNode.replaceChild(htmlvideo, elem); - } + return htmlvideo; + } + + function init_flash_player(div_id, width, height, video_url, thumb_url) + { + var swf = "/static/default/flowplayer/flowplayer-3.2.18.swf"; + + var style = 'width: ' + width + 'px; height: ' + height + 'px; display: block'; + document.getElementById(div_id).style.cssText += ';' + style; + + flashembed(div_id, swf, {config: + { + clip: { + url: video_url + }, + + plugins: { + rangeRequests: true + } + + }}); } document.addEventListener("DOMContentLoaded", check_videos); diff --git a/pywb/ui/head_insert.html b/pywb/ui/head_insert.html index 65397c9d..5200cdf8 100644 --- a/pywb/ui/head_insert.html +++ b/pywb/ui/head_insert.html @@ -25,6 +25,10 @@ wbinfo.proxy_magic = "{{ wbrequest.env.pywb_proxy_magic }}"; + + + + diff --git a/setup.py b/setup.py index 2fe33078..0aae5636 100755 --- a/setup.py +++ b/setup.py @@ -42,6 +42,7 @@ setup( long_description=long_description, license='GPL', packages=find_packages(), + include_package_data=True, provides=[ 'pywb', 'pywb.utils', @@ -54,7 +55,7 @@ setup( 'pywb.apps' ], package_data={ - 'pywb': ['ui/*', 'static/*', '*.yaml'], + 'pywb': ['static/flowplayer/*', 'static/*.*', 'ui/*', '*.yaml'], }, data_files=[ ('sample_archive/cdx/', glob.glob('sample_archive/cdx/*')),