') + ')', 'gi');
if (regex.test(text)) {
found = true;
var frag = document.createDocumentFragment();
var parts = text.split(regex);
parts.forEach(function(part, i) {
if (i % 2 === 0) {
frag.appendChild(document.createTextNode(part));
} else {
var span = document.createElement('span');
span.className = 'userscript-highlight';
span.textContent = part;
frag.appendChild(span);
}
});
node.parentNode.replaceChild(frag, node);
}
});
} else if (node.nodeType === 1 && node.childNodes) { // element
var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];
if (!skipTags.includes(node.tagName)) {
Array.from(node.childNodes).forEach(highlight);
}
}
}
highlight(document.body);
// Re-highlight on dynamic content
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
m.addedNodes.forEach(function(node) {
if (node.nodeType === 1 || node.nodeType === 3) highlight(node);
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); }
})();
(function(){
try {
var __m = "*";
var __re = new RegExp('^' + ".*" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Strip utm_, fbclid, gclid, etc. from all links on page
(function() {
var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',
'ref', 'ref_src', 'source', 'medium', 'campaign'];
function cleanUrl(url) {
try {
var u = new URL(url, window.location.origin);
var changed = false;
trackingParams.forEach(function(p) {
if (u.searchParams.has(p)) {
u.searchParams.delete(p);
changed = true;
}
});
return changed ? u.toString() : url;
} catch (e) {
return url;
}
}
function cleanLinks() {
document.querySelectorAll('a[href]').forEach(function(a) {
var clean = cleanUrl(a.href);
if (clean !== a.href) a.href = clean;
});
}
cleanLinks();
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
m.addedNodes.forEach(function(node) {
if (node.nodeType === 1) {
if (node.tagName === 'A') cleanLinks();
node.querySelectorAll('a[href]').forEach(function(a) {
var clean = cleanUrl(a.href);
if (clean !== a.href) a.href = clean;
});
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); }
})();
(function(){
try {
var __m = "youtube.com";
var __re = new RegExp('^' + "youtube\\.com" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Auto-enable theater mode on YouTube
(function() {
function tryTheater() {
var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]');
if (btn && !btn.classList.contains('activated')) {
btn.click();
}
}
// Try immediately
tryTheater();
// Try after navigation (SPA)
var lastUrl = location.href;
setInterval(function() {
if (location.href !== lastUrl) {
lastUrl = location.href;
setTimeout(tryTheater, 500);
}
}, 1000);
// Also try on player load
var observer = new MutationObserver(tryTheater);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); }
})();
(function(){
try {
var __m = "*";
var __re = new RegExp('^' + ".*" + ', 'i');
if (__m === '*' || __re.test(location.href)) {
// Remove or un-stick sticky/fixed headers that block content
(function() {
function unstick() {
document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) {
if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {
el.style.position = 'static';
el.style.top = 'auto';
el.style.zIndex = 'auto';
}
});
}
unstick();
var observer = new MutationObserver(unstick);
observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
})();
}
} catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); }
})();
})();
GitHub - fredchung/record: Audio recorder from microphone to a given file path. No external dependencies, MediaRecorder is used for Android an AVAudioRecorder for iOS. · GitHub
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Audio recorder from microphone to a given file path or stream.
No external dependencies:
On Android, AudioRecord and MediaCodec.
On iOS and macOS, AVFoundation.
On Windows, MediaFoundation.
On web, well... your browser! (and its underlying platform).
External dependencies:
On linux, encoding is provided by fmedia. It must be installed separately.
Platform feature parity matrix
Feature
Android
iOS
web
Windows
macOS
linux
pause/resume
✔️
✔️
✔️
✔️
✔️
✔️
amplitude(dBFS)
✔️
✔️
✔️
✔️
✔️
permission check
✔️
✔️
✔️
✔️
num of channels
✔️
✔️
✔️
✔️
✔️
✔️
device selection
✔️ *
(auto BT/mic)
✔️
✔️
✔️
✔️
auto gain
✔️
(always active?)
✔️
echo cancel
✔️
✔️
noise suppresion
✔️
✔️
min SDK: 23. Bluetooth telephony device link (SCO) is automatically done but there's no phone call management.
File
Encoder
Android
iOS
web
Windows
macOS
linux
aacLc
✔️
✔️
?
✔️
✔️
✔️
aacEld
✔️
✔️
?
✔️
aacHe
✔️
?
✔️
amrNb
✔️
?
✔️
amrWb
✔️
?
opus
✔️
✔️
✔️
wav
✔️
✔️
✔️
✔️
✔️
✔️
flac
✔️
✔️
?
✔️
✔️
✔️
pcm16bits
✔️
✔️
✔️
✔️
✔️
* Question marks (?) in web column mean that the formats are supported by the plugin
but are not available in current (and tested) browsers (Chrome / Firefox).
Stream
Encoder
Android
iOS
web
Windows
macOS
linux
aacLc *
✔️
aacEld *
✔️
aacHe *
✔️
pcm16bits
✔️
✔️
✔️
✔️
✔️
* AAC is streamed with raw AAC with ADTS headers, so it's directly readable through a file!
All audio output is with 16bits depth.
Usage
import'package:record/record.dart';
final record =AudioRecorder();
// Check and request permission if neededif (await record.hasPermission()) {
// Start recording to fileawait record.start(constRecordConfig(), path:'aFullPath/myFile.m4a');
// ... or to streamfinal stream =await record.startStream(constRecordConfig(AudioEncoder.pcm16bits));
}
// Stop recording...final path =await record.stop();
// ... or cancel it (and implicitly remove file/blob).await record.cancel();
record.dispose(); // As always, don't forget this one.
Setup, permissions and others
Android
<uses-permissionandroid:name="android.permission.RECORD_AUDIO" />
<!-- Optional: Add this permission if you want to use bluetooth telephony device like headset/earbuds (min SDK: 23) -->
<uses-permissionandroid:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!-- Optional: Add this permission if you want to save your recordings in public folders -->
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE" />