├── icon.png ├── icons ├── icon128.png ├── icon48.png └── icon64.png ├── noncode ├── screenshot_video.png ├── screenshot_support.png └── screenshot_support_future.png ├── package.json ├── README.md ├── index.js └── data ├── content_script.js └── inject.js /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/HEAD/icon.png -------------------------------------------------------------------------------- /icons/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/HEAD/icons/icon128.png -------------------------------------------------------------------------------- /icons/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/HEAD/icons/icon48.png -------------------------------------------------------------------------------- /icons/icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/HEAD/icons/icon64.png -------------------------------------------------------------------------------- /noncode/screenshot_video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/HEAD/noncode/screenshot_video.png -------------------------------------------------------------------------------- /noncode/screenshot_support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/HEAD/noncode/screenshot_support.png -------------------------------------------------------------------------------- /noncode/screenshot_support_future.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/HEAD/noncode/screenshot_support_future.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "h264ify", 3 | "description": "Makes YouTube stream H.264 videos instead of VP8/VP9 videos", 4 | "version": "1.0.5", 5 | "author": "erkserkserks", 6 | "engines": { 7 | "firefox": ">= 38.0a1", 8 | "fennec": ">= 38.0a1" 9 | }, 10 | "homepage": "https://github.com/erkserkserks/h264ify-firefox", 11 | "icon": "icon.png", 12 | "id": "jid1-TSgSxBhncsPBWQ@jetpack", 13 | "license": "MIT", 14 | "permissions": { 15 | "multiprocess": true, 16 | "private-browsing": true 17 | }, 18 | "preferences": [ 19 | { 20 | "name": "enable", 21 | "title": "Enable h264ify", 22 | "type": "bool", 23 | "value": true 24 | }, 25 | { 26 | "name": "block_60fps", 27 | "title": "Block 60fps", 28 | "type": "bool", 29 | "value": false 30 | } 31 | ], 32 | "title": "h264ify" 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 3 | 4 | # h264ify-firefox 5 | 6 | ![](https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/master/noncode/screenshot_video.png) 7 | 8 | # About 9 | h264ify is a Firefox/Chrome extension that makes YouTube stream H.264 videos instead of VP8/VP9 videos. 10 | 11 | Try h264ify if YouTube videos stutter, take up too much CPU, eat battery life, or make your laptop hot. 12 | 13 | By default, YouTube streams VP8/VP9 encoded video. However, this can cause problems with less powerful machines because VP8/VP9 is not typically hardware accelerated. 14 | 15 | In contrast, H.264 is commonly hardware accelerated by GPUs, which usually means smoother video playback and reduced CPU usage. 16 | 17 | # Requirements 18 | Firefox 19 | 20 | Looking for the Chrome version? See: https://github.com/erkserkserks/h264ify 21 | 22 | # Installation 23 | Install from here: https://addons.mozilla.org/firefox/addon/h264ify/ 24 | 25 | If all goes well, when you visit https://www.youtube.com/html5, you should see this: 26 | ![](https://raw.githubusercontent.com/erkserkserks/h264ify-firefox/master/noncode/screenshot_support.png) 27 | 28 | Note: The current version of Firefox (35) doesn't support MSE, but when support arrives, h264ify will also block VP9. 29 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 erkserkserks 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | var data = require('sdk/self').data; 26 | var pageMod = require('sdk/page-mod'); 27 | 28 | pageMod.PageMod({ 29 | include: '*.youtube.com', 30 | contentScriptWhen: 'start', 31 | contentScriptFile: data.url('content_script.js'), 32 | contentScriptOptions: {'injectjsText' : data.load('inject.js')}, 33 | onAttach: function(worker) { 34 | worker.port.emit('prefs', require('sdk/simple-prefs').prefs); 35 | 36 | function onPrefChange(prefName) { 37 | worker.port.emit('prefs', require('sdk/simple-prefs').prefs); 38 | } 39 | require('sdk/simple-prefs').on('', onPrefChange); 40 | } 41 | }); 42 | 43 | -------------------------------------------------------------------------------- /data/content_script.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 erkserkserks 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | // This content script runs in an isolated environment and cannot modify any 26 | // javascript variables on the youtube page. Thus, we have to inject another 27 | // script into the DOM using a script tag. 28 | 29 | // Set defaults for options stored in localStorage 30 | if (localStorage['h264ify-enable'] === undefined) { 31 | localStorage['h264ify-enable'] = true; 32 | } 33 | if (localStorage['h264ify-block_60fps'] === undefined) { 34 | localStorage['h264ify-block_60fps'] = false; 35 | } 36 | 37 | // Cache extension preferences in localStorage. 38 | // This is needed because port.on is async and we want to 39 | // load the injection script immediately. 40 | self.port.on('prefs', function(prefs) { 41 | console.log('port on prefs') 42 | localStorage['h264ify-enable'] = prefs['enable']; 43 | localStorage['h264ify-block_60fps'] = prefs['block_60fps']; 44 | }); 45 | 46 | // Create script elem which will be injected into the page 47 | var script = document.createElement('script'); 48 | script.type = 'text/javascript'; 49 | // Use textContent instead of src to run inject.js synchronously 50 | script.textContent = self.options.injectjsText; 51 | var html = document.documentElement; 52 | // Inject js into the page 53 | html.insertBefore(script, html.firstChild); 54 | // Clean up 55 | script.remove() 56 | -------------------------------------------------------------------------------- /data/inject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 erkserkserks 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | (function () { 26 | if (localStorage['h264ify-enable'] === 'false') { 27 | return; 28 | } 29 | 30 | // return a custom MIME type checker that can defer to the original function 31 | function makeModifiedMimeTypeChecker(origFunc) { 32 | return function (type) { 33 | if (type === undefined) return ''; 34 | 35 | var disallowed_types = ['webm', 'vp8', 'vp9']; 36 | // If video type is in disallowed_types, say we don't support them 37 | for (var i = 0; i < disallowed_types.length; i++) { 38 | if (type.indexOf(disallowed_types[i]) != -1) return ''; 39 | } 40 | 41 | if (localStorage['h264ify-block_60fps'] === 'true') { 42 | var match = /framerate=(\d+)/.exec(type); 43 | if (match && match[1] > 30) return ''; 44 | } 45 | 46 | // Otherwise, ask the browser 47 | return origFunc(type); 48 | }; 49 | } 50 | 51 | // Override video element canPlayType() function 52 | var videoElem = document.createElement('video'); 53 | var origCanPlayType = videoElem.canPlayType.bind(videoElem); 54 | videoElem.__proto__.canPlayType = makeModifiedMimeTypeChecker(origCanPlayType); 55 | 56 | // Override media source extension isTypeSupported() function 57 | var mse = window.MediaSource; 58 | // Check for MSE support before use - some versions of FF don't support MSE 59 | if (mse === undefined) return; 60 | var origIsTypeSupported = mse.isTypeSupported.bind(mse); 61 | mse.isTypeSupported = makeModifiedMimeTypeChecker(origIsTypeSupported); 62 | })(); 63 | 64 | --------------------------------------------------------------------------------