Compare commits

...
4 Commits
6 changed files with 105 additions and 11 deletions
+1
View File
@@ -114,6 +114,7 @@ const sponsors = {
{ image: 'https://avatars.githubusercontent.com/u/2698271', name: 'Matthew Gardner', url: 'https://github.com/spheric' },
{ image: 'https://avatars.githubusercontent.com/u/5475819', name: 'AJ Funk', url: 'https://github.com/AJFunk' },
{ image: 'https://avatars.githubusercontent.com/u/30229596', name: 'Pablo Bonilla', url: 'https://github.com/devPablo' },
{ image: 'https://avatars.githubusercontent.com/u/56988069', name: 'SyhabouthAlex', url: 'https://github.com/SyhabouthAlex' },
{ image: 'https://avatars.githubusercontent.com/u/38181164', name: 'wcw', url: 'https://github.com/asd55667' },
{ image: 'https://avatars.githubusercontent.com/u/1836701', name: 'Bean Deng', url: 'https://github.com/HADB' },
{ image: 'https://avatars.githubusercontent.com/u/63088713', name: 'taf2000', url: 'https://github.com/taf2000' },
+6 -6
View File
@@ -1,12 +1,12 @@
{
"name": "mediabunny",
"version": "1.25.7",
"version": "1.25.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mediabunny",
"version": "1.25.7",
"version": "1.25.8",
"license": "MPL-2.0",
"workspaces": [
"packages/*"
@@ -7739,9 +7739,9 @@
}
},
"node_modules/mediabunny": {
"version": "1.25.6",
"resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.25.6.tgz",
"integrity": "sha512-0CUgi9oHbyzPHZttn6aCQrWZLUpSAb7m1QKSSjr780LU0bgF2rgsYXAzPwt0V9ScK0t5CPuVhlmxF8MVe5BFHw==",
"version": "1.25.7",
"resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.25.7.tgz",
"integrity": "sha512-DL0E1h29HTDaD9bYRXLSSHiAoLbDBksrdYS+4OHWA+aNhQeN+CAGEG7EU6wlhPZ8MOpwXIeC7uv06lo4ziohQQ==",
"license": "MPL-2.0",
"peer": true,
"workspaces": [
@@ -12065,7 +12065,7 @@
},
"packages/mp3-encoder": {
"name": "@mediabunny/mp3-encoder",
"version": "1.25.7",
"version": "1.25.8",
"license": "MPL-2.0",
"devDependencies": {
"@types/emscripten": "^1.40.1"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "mediabunny",
"author": "Vanilagy",
"version": "1.25.7",
"version": "1.25.8",
"description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.",
"type": "module",
"workspaces": [
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@mediabunny/mp3-encoder",
"author": "Vanilagy",
"version": "1.25.7",
"version": "1.25.8",
"description": "MP3 encoder extension for Mediabunny, based on LAME.",
"main": "./dist/bundles/mediabunny-mp3-encoder.mjs",
"module": "./dist/bundles/mediabunny-mp3-encoder.mjs",
+65 -1
View File
@@ -22,6 +22,8 @@ import {
textEncoder,
toDataView,
toUint8Array,
getChromiumVersion,
isChromium,
} from './misc';
import { PacketType } from './packet';
import { MetadataTags } from './metadata';
@@ -34,6 +36,7 @@ import { MetadataTags } from './metadata';
export enum AvcNalUnitType {
IDR = 5,
SEI = 6,
SPS = 7,
PPS = 8,
SPS_EXT = 13,
@@ -1714,7 +1717,68 @@ export const determineVideoPacketType = (
switch (codec) {
case 'avc': {
const nalUnits = extractAvcNalUnits(packetData, decoderConfig);
const isKeyframe = nalUnits.some(x => extractNalUnitTypeForAvc(x) === AvcNalUnitType.IDR);
let isKeyframe = nalUnits.some(x => extractNalUnitTypeForAvc(x) === AvcNalUnitType.IDR);
if (!isKeyframe && (!isChromium() || getChromiumVersion()! >= 144)) {
// In addition to IDR, Recovery Point SEI also counts as a valid H.264 keyframe by current consensus.
// See https://github.com/w3c/webcodecs/issues/650 for the relevant discussion. WebKit and Firefox have
// always supported them, but Chromium hasn't, therefore the (admittedly dirty) version check.
for (const nalUnit of nalUnits) {
const type = extractNalUnitTypeForAvc(nalUnit);
if (type !== AvcNalUnitType.SEI) {
continue;
}
const bytes = removeEmulationPreventionBytes(nalUnit);
let pos = 1; // Skip NALU header
// sei_rbsp()
do {
// sei_message()
let payloadType = 0;
while (true) {
const nextByte = bytes[pos++];
if (nextByte === undefined) break;
payloadType += nextByte;
if (nextByte < 255) {
break;
}
}
let payloadSize = 0;
while (true) {
const nextByte = bytes[pos++];
if (nextByte === undefined) break;
payloadSize += nextByte;
if (nextByte < 255) {
break;
}
}
// sei_payload()
const PAYLOAD_TYPE_RECOVERY_POINT = 6;
if (payloadType === PAYLOAD_TYPE_RECOVERY_POINT) {
const bitstream = new Bitstream(bytes);
bitstream.pos = 8 * pos;
const recoveryFrameCount = readExpGolomb(bitstream);
const exactMatchFlag = bitstream.readBits(1);
if (recoveryFrameCount === 0 && exactMatchFlag === 1) {
// https://github.com/w3c/webcodecs/pull/910
// "recovery_frame_cnt == 0 and exact_match_flag=1 in the SEI recovery payload"
isKeyframe = true;
break;
}
}
pos += payloadSize;
} while (pos < bytes.length - 1);
}
}
return isKeyframe ? 'key' : 'delta';
};
+31 -2
View File
@@ -679,7 +679,15 @@ export const isWebKit = () => {
}
// This even returns true for WebKit-wrapping browsers such as Chrome on iOS
return isWebKitCache = !!(typeof navigator !== 'undefined' && navigator.vendor?.match(/apple/i));
return isWebKitCache = !!(
typeof navigator !== 'undefined'
&& (
navigator.vendor?.match(/apple/i)
// Or, in workers:
|| (/AppleWebKit/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent))
|| /\b(iPad|iPhone|iPod)\b/.test(navigator.userAgent)
)
);
};
let isFirefoxCache: boolean | null = null;
@@ -697,7 +705,28 @@ export const isChromium = () => {
return isChromiumCache;
}
return isChromiumCache = !!(typeof navigator !== 'undefined' && navigator.vendor?.includes('Google Inc'));
return isChromiumCache = !!(
typeof navigator !== 'undefined'
&& (navigator.vendor?.includes('Google Inc') || /Chrome/.test(navigator.userAgent))
);
};
let chromiumVersionCache: number | null = null;
export const getChromiumVersion = () => {
if (chromiumVersionCache !== null) {
return chromiumVersionCache;
}
if (typeof navigator === 'undefined') {
return null;
}
const match = /\bChrome\/(\d+)/.exec(navigator.userAgent);
if (!match) {
return null;
}
return chromiumVersionCache = Number(match[1]!);
};
/**