This is a lib based on ts-ebml and support large file (>2GB) that ts-ebml not supported
Using this function can not only add "Duration" but also add "SeekHead", "Seek", "SeekID", "SeekPosition" and "Cues", "CueTime", "CueTrack", "CueClusterPosition", "CueTrackPositions", "CuePoint" for a webm file
import fixWebmMetaInfo from "webm-metainfo-fix";
// please use h264 to enable hardware encode accelerate and decrease cpu usage
const mimeType = "video/webm;codecs=h264";
const blobSlice: BlobPart[] = [];
mediaRecorder = new MediaRecorder(stream, {
mimeType,
videoBitsPerSecond: 1e6,
});
mediaRecorder.ondataavailable = (event: BlobEvent) => {
blobSlice.push(event.data);
};
mediaRecorder.onstop = async () => {
// support fix webm files larger than 2GB
const fixedWebMBlob = await fixWebmMetaInfo(
new Blob([...blobSlice], { type: mimeType }),
duration
);
blobSlice = [];
};
// using timeslice to avoid memory consumption in renderer process, and generate a blob object each second
mediaRecorder.start(1000);
setTimeout(() => mediaRecorder.stop(), 5000); // generate 5 blob slices
fix: Custom duration
fix: update webm matroska-schema to V4 version
fix: using Blob instead of ArrayBuffer to fix recreate webm issue and solving memory leak
Currently each record will have a maxiumm 5MB memory leak (already the best result, because chromium internal blob <-> arrayBuffer process has some kind of bug, and webm meta head will leak for each video record, seen in: chrome://blob-internals), if you have the ability to modify chromium, this value can decrease down to 1MB or even much smaller size.
The only way is to modify chromium project, here is the example:
// storage/browser/blob/blob_storage_constants.cc
#if defined(OS_ANDROID)
// On minimal Android maximum in-memory space can be as low as 5MB.
constexpr uint64_t kDefaultMinPageFileSize = 5ull * 1024 * 1024 / 2;
const float kDefaultMaxBlobInMemorySpaceUnderPressureRatio = 0.02f;
#else
// fix1: change 5MB minPageSize to 1MB
constexpr uint64_t kDefaultMinPageFileSize = 1ull * 1024 * 1024;
const float kDefaultMaxBlobInMemorySpaceUnderPressureRatio = 0.002f;
#endif
According to the chromium blob implention, this value equals to Math.min(software located disk partition size * / 10, free disk space), so if your C:\ partition is 128GB, the max record size is 12.8GB, even if you have 100GB free space.
The only way is modify chromium project, here is the example:
// storage/browser/blob/blob_memory_controller.cc
if (disk_size >= 0) {
#if defined(OS_CHROMEOS)
limits.desired_max_disk_space = static_cast<uint64_t>(disk_size / 2ll);
#elif defined(OS_ANDROID)
limits.desired_max_disk_space = static_cast<uint64_t>(3ll * disk_size / 50);
#else
// fix2: make file limit from 1/10 disk size to 1/1
limits.desired_max_disk_space = static_cast<uint64_t>(disk_size);
#endif
}
Because Blob creation has a Renderer -> Main -> Memory/Disk Transport process, and if no mediaRecord.RequestData() called or timeslice specified, then all data will be buffered in the renderer process, we have to clear the data in memory.
Because Blob designed to be store in sharedMemory initially, and if the memory is not enough to store, it will use disk space to store blob afterward.
The only way is to modify chromium project, here is the example:
// storage/browser/blob/blob_memory_controller.cc
if (memory_size > 0) {
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
// fix3: make 2GB -> 200MB to decrease main process memory usage
constexpr size_t kTwoHundrendMegabytes = 2ull * 100 * 1024 * 1024;
limits.max_blob_in_memory_space = kTwoHundrendMegabytes;
#elif defined(OS_ANDROID)
limits.max_blob_in_memory_space = static_cast<size_t>(memory_size / 100ll);
#else
limits.max_blob_in_memory_space = static_cast<size_t>(memory_size / 5ll);
#endif
}
- using web worker to decrease thread crimp (already implement, will suport later)
- decrease runtime fix memory consumption
- support non-node enviroment fixup