Kaydol

Merhaba Sevgili Floodlar.com Kullanıcısı, Web sitemizde geçirdiğiniz zaman ve bu büyüleyici flood evrenine katılımınız için teşekkür ederiz. Floodların geniş dünyasıyla dolu deneyiminizi daha fazla keşfetmek için, web sitemizi sınırsız olarak kullanabilmeniz adına giriş yapmanız gerekmektedir.

Oturum aç

Merhaba Floodlar.com Kullanıcısı, İlk üç sayfayı tamamladınız, tebrikler! Ancak, floodların devamını görmek ve daha fazla interaktif deneyim yaşamak için giriş yapmanız gerekiyor. Hesabınız yoksa, hızlıca oluşturabilirsiniz. Sınırsız floodlar ve etkileşimler sizleri bekliyor. Giriş yapmayı unutmayın!

Şifremi hatırlamıyorum

Şifreniz mi unuttunuz? Endişelenmeyin! Lütfen kayıtlı e-posta adresinizi giriniz. Size bir bağlantı göndereceğiz ve bu link üzerinden yeni bir şifre oluşturabileceksiniz.

Fil Necati Masonlar Locası Subreddit Adı Nedir? Cevap: ( N31 )

Üzgünüz, flood girme izniniz yok, Flood girmek için giriş yapmalısınız.

Lütfen bu Floodun neden bildirilmesi gerektiğini düşündüğünüzü kısaca açıklayın.

Lütfen bu cevabın neden bildirilmesi gerektiğini kısaca açıklayın.

Lütfen bu kullanıcının neden rapor edilmesi gerektiğini düşündüğünüzü kısaca açıklayın.

Mobil Uygulamada Açın

Güncel Floodlar En sonuncu Nesne

Kapwing: Web için güçlü video düzenleme

Kapwing: Web için güçlü video düzenleme

Çevrimiçi video tüketimi, pandeminin başlangıcından bu yana hızla arttı. İnsanlar, TikTok, Instagram ve YouTube gibi platformlarda sonsuz yüksek kaliteli video tüketmek için daha fazla zaman harcıyor. Tüm dünyadaki kreatifler ve küçük işletme sahipleri, video içeriği oluşturmak için hızlı ve kullanımı kolay araçlara ihtiyaç duyar.

Kapwing gibi şirketler, en yeni güçlü API’leri ve performans araçlarını kullanarak tüm bu video içeriğini doğrudan web üzerinde oluşturmayı mümkün kılar.

Kapwing Hakkında #

Kapwing, esas olarak oyun yayıncıları, müzisyenler, YouTube içerik oluşturucuları ve meme-rs gibi sıradan yaratıcılar için tasarlanmış, web tabanlı, ortak çalışmaya dayalı bir video düzenleyicidir. Ayrıca, Facebook ve Instagram reklamları gibi kendi sosyal içeriklerini oluşturmak için kolay bir yola ihtiyaç duyan işletme sahipleri için başvurulacak bir kaynaktır.

İnsanlar Kapwing’i “bir video nasıl kırpılır”, “videoma müzik ekle” veya “videoyu yeniden boyutlandırma” gibi belirli bir görevi arayarak keşfeder. Bir uygulama mağazasına gitme ve bir uygulama indirme zahmetine katlanmadan, aradıklarını tek bir tıklamayla yapabilirler. Web, insanların tam olarak hangi görevde yardıma ihtiyaç duyduklarını aramasını ve ardından bunu yapmasını kolaylaştırır.

Bu ilk tıklamadan sonra, Kapwing kullanıcıları çok daha fazlasını yapabilir. Ücretsiz şablonları keşfedebilir, yeni ücretsiz stok video katmanları ekleyebilir, altyazı ekleyebilir, videoları yazıya dökebilir ve arka plan müziği yükleyebilirler.

Kapwing, web’e gerçek zamanlı düzenleme ve işbirliğini nasıl getiriyor? #

Web benzersiz avantajlar sağlarken, aynı zamanda farklı zorluklar da sunar. Kapwing’in karmaşık, çok katmanlı projelerin çok çeşitli cihazlarda ve ağ koşullarında sorunsuz ve hassas bir şekilde oynatılması gerekiyor. Bunu başarmak için, performans ve özellik hedeflerimize ulaşmak için çeşitli web API’leri kullanıyoruz.

IndexedDB #

Yüksek performanslı düzenleme, mümkün olduğunca ağdan kaçınarak, kullanıcılarımızın tüm içeriğinin istemcide yaşamasını gerektirir. Kullanıcıların bir içeriğe genellikle bir kez eriştiği bir akış hizmetinin aksine, müşterilerimiz varlıklarını yüklemeden günler ve hatta aylar sonra sık sık yeniden kullanır.

IndexedDB, kullanıcılarımıza kalıcı dosya sistemi benzeri depolama sağlamamıza olanak tanır. Sonuç, uygulamadaki medya isteklerinin %90’ından fazlasının yerel olarak karşılanmasıdır. IndexedDB’yi sistemimize entegre etmek çok basitti.

İşte uygulama yükünde çalışan bazı standart başlatma kodu:

import {DBSchema, openDB, deleteDB, IDBPDatabase} from 'idb';

let openIdb: Promise IDBPDatabaseSchema>>;

const db =
(await openDB)
Schema >
(
'kapwing',
version, {
upgrade(db, oldVersion) {
if (oldVersion >= 1) {
// assets store schema changed, need to recreate
db.deleteObjectStore('assets');
}

db.createObjectStore('assets', {
keyPath: 'mediaLibraryID'
});
},
async blocked() {
await deleteDB('kapwing');
},
async blocking() {
await deleteDB('kapwing');
},
}
);

Bir sürümü geçiyoruz ve bir tanımlıyoruz upgrade işlev. Bu, başlatma için veya gerektiğinde şemamızı güncellemek için kullanılır. Hata işleyen geri aramaları geçiyoruz, blocked Ve blockingkararsız sistemlere sahip kullanıcılar için sorunları önlemede yararlı bulduk.

Son olarak, birincil anahtar tanımımıza dikkat edin. keyPath. Bizim durumumuzda, bu, dediğimiz benzersiz bir kimliktir. mediaLibraryID. Bir kullanıcı, yükleyicimiz veya üçüncü taraf bir uzantı aracılığıyla sistemimize bir medya parçası eklediğinde, medyayı aşağıdaki kodla medya kitaplığımıza ekleriz:

export async function addAsset(mediaLibraryID: string, file: File) {
return runWithAssetMutex(mediaLibraryID, async () => {
const assetAlreadyInStore = await (await openIdb).get(
'assets',
mediaLibraryID
);
if (assetAlreadyInStore) return;

const idbVideo: IdbVideo = {
file,
mediaLibraryID,
};

await (await openIdb).add('assets', idbVideo);
});
}

runWithAssetMutex IndexedDB erişimini seri hale getiren kendi dahili olarak tanımlanmış fonksiyonumuzdur. IndexedDB API’si eşzamansız olduğundan, okuma-değiştirme-yazma türü işlemler için bu gereklidir.

Şimdi dosyalara nasıl eriştiğimize bir göz atalım. Aşağıda bizim getAsset işlev:

export async function getAsset(
mediaLibraryID: string,
source: LayerSource | null | undefined,
location: string

): PromiseIdbAsset | undefined> {
let asset: IdbAsset | undefined;
const { idbCache } = window;
const assetInCache = idbCache[mediaLibraryID];

if (assetInCache && assetInCache.status === 'complete') {
asset = assetInCache.asset;
} else if (assetInCache && assetInCache.status === 'pending') {
asset = await new Promise((res) => {
assetInCache.subscribers.push(res);
});
} else {
idbCache[mediaLibraryID] = { subscribers: [], status: 'pending' };
asset = (await openIdb).get('assets', mediaLibraryID);

idbCache[mediaLibraryID].asset = asset;
idbCache[mediaLibraryID].subscribers.forEach((res: any) => {
res(asset);
});

delete (idbCache[mediaLibraryID] as any).subscribers;

if (asset) {
idbCache[mediaLibraryID].status = 'complete';
} else {
idbCache[mediaLibraryID].status = 'failed';
}
}
return asset;
}

Kendi veri yapımız var, idbCache, IndexedDB erişimlerini en aza indirmek için kullanılır. IndexedDB hızlı olsa da, yerel belleğe erişim daha hızlıdır. Önbelleğin boyutunu yönettiğiniz sürece bu yaklaşımı öneririz.

bu subscribers IndexedDB’ye eşzamanlı erişimi engellemek için kullanılan dizi, aksi takdirde yükte ortak olacaktır.

Web Ses API’sı #

Ses görselleştirme, video düzenleme için inanılmaz derecede önemlidir. Nedenini anlamak için düzenleyiciden bir ekran görüntüsüne bakın:

Bu, uygulamamızda yaygın olarak kullanılan YouTube tarzı bir videodur. Kullanıcı klip boyunca çok fazla hareket etmez, bu nedenle zaman çizelgesi görsel küçük resimleri, bölümler arasında gezinmek için o kadar kullanışlı değildir. Öte yandan, ses dalga biçimi tipik olarak kayıttaki ölü zamana karşılık gelen vadilerle zirveleri ve vadileri gösterir. Zaman çizelgesini yakınlaştırırsanız, teklemelere ve duraklamalara karşılık gelen vadilerle birlikte daha ayrıntılı ses bilgileri görürsünüz.

Kullanıcı araştırmamız, içerik oluşturucuların içeriklerini eklerken genellikle bu dalga biçimleri tarafından yönlendirildiğini gösteriyor. Web ses API’si, bu bilgileri performanslı bir şekilde sunmamıza ve zaman çizelgesinin yakınlaştırılmasında veya kaydırılmasında hızlı bir şekilde güncelleme yapmamıza olanak tanır.

Aşağıdaki kod parçası bunu nasıl yaptığımızı göstermektedir:

const getDownsampledBuffer = (idbAsset: IdbAsset) =>
decodeMutex.runExclusive(
async (): PromiseFloat32Array> => {
const arrayBuffer = await idbAsset.file.arrayBuffer();
const audioContext = new AudioContext();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);

const offline = new OfflineAudioContext(
audioBuffer.numberOfChannels,
audioBuffer.duration * MIN_BROWSER_SUPPORTED_SAMPLE_RATE,
MIN_BROWSER_SUPPORTED_SAMPLE_RATE
);

const downsampleSource = offline.createBufferSource();
downsampleSource.buffer = audioBuffer;
downsampleSource.start(0);
downsampleSource.connect(offline.destination);

const downsampledBuffer22K = await offline.startRendering();

const downsampledBuffer22KData = downsampledBuffer22K.getChannelData(0);

const downsampledBuffer = new Float32Array(
Math.floor(
downsampledBuffer22KData.length / POST_BROWSER_SAMPLE_INTERVAL
)
);

for (
let i = 0, j = 0;
i downsampledBuffer22KData.length;
i += POST_BROWSER_SAMPLE_INTERVAL, j += 1
) {
let sum = 0;
for (let k = 0; k POST_BROWSER_SAMPLE_INTERVAL; k += 1) {
sum += Math.abs(downsampledBuffer22KData[i + k]);
}
const avg = sum / POST_BROWSER_SAMPLE_INTERVAL;
downsampledBuffer[j] = avg;
}

return downsampledBuffer;
}
);

Bu yardımcıya IndexedDB’de saklanan varlığı aktarıyoruz. Tamamlandıktan sonra IndexedDB’deki varlığı ve kendi önbelleğimizi güncelleyeceğiz.

hakkında veri topluyoruz. audioBuffer ile AudioContext yapıcı, ancak cihaz donanımını oluşturmadığımız için OfflineAudioContext hale getirmek için ArrayBuffer genlik verilerini saklayacağımız yer.

API’nin kendisi, verileri etkili görselleştirme için gerekenden çok daha yüksek bir örnekleme hızında döndürür. Bu nedenle, kullanışlı, görsel olarak çekici dalga biçimleri için yeterli bulduğumuz 200 Hz’e manuel olarak alt örnekleme yapıyoruz.

WebKodlayıcılar #

Belirli videolar için parça küçük resimleri, zaman çizelgesinde gezinmek için dalga biçimlerinden daha kullanışlıdır. Ancak küçük resimler oluşturmak, dalga biçimleri oluşturmaktan daha yoğun kaynak gerektirir.

Yükleme sırasında her olası küçük resmi önbelleğe alamıyoruz, bu nedenle zaman çizelgesi kaydırma/yakınlaştırmada hızlı kod çözme, performanslı ve duyarlı bir uygulama için çok önemlidir. Pürüzsüz çerçeve çizimi elde etmenin darboğazı, yakın zamana kadar bir HTML5 video oynatıcı kullanarak yaptığımız çerçevelerin kodunu çözmektir. Bu yaklaşımın performansı güvenilir değildi ve çerçeve oluşturma sırasında uygulama yanıt hızının düştüğünü sık sık gördük.

Son zamanlarda web çalışanlarında kullanılabilen WebCodec’lere geçtik. Bu, ana iş parçacığı performansını etkilemeden büyük miktarda katman için küçük resim çizme yeteneğimizi geliştirmelidir. Web çalışanı uygulaması hala devam ederken, aşağıda mevcut ana iş parçacığı uygulamamızın ana hatlarını veriyoruz.

Bir video dosyası birden çok akış içerir: video, ses, altyazılar vb. WebCodec’leri kullanmak için, önce birleştirilmiş bir video akışına sahip olmamız gerekir. Burada gösterildiği gibi mp4’leri mp4box kitaplığıyla ayırıyoruz:

async function create(demuxer: any) {
demuxer.file = (await MP4Box).createFile();
demuxer.file.onReady = (info: any) => {
demuxer.info = info;
demuxer._info_resolver(info);
};
demuxer.loadMetadata();
}

const loadMetadata = async () => {
let offset = 0;
const asset = await getAsset(this.mediaLibraryId, null, this.url);
const maxFetchOffset = asset?.file.size || 0;

const end = offset + FETCH_SIZE;
const response = await fetch(this.url, {
headers: { range: `bytes=${offset}-${end}` },
});
const reader = response.body.getReader();

let done, value;
while (!done) {
({ done, value } = await reader.read());
if (done) {
this.file.flush();
break;
}

const buf: ArrayBufferLike & { fileStart?: number } = value.buffer;
buf.fileStart = offset;
offset = this.file.appendBuffer(buf);
}
};

Bu parçacığın bir demuxer arayüzü kapsüllemek için kullandığımız sınıf MP4Box. Varlığa bir kez daha IndexedDB’den erişiyoruz. Bu segmentler mutlaka bayt sırasına göre saklanmaz ve appendBuffer yöntem, bir sonraki parçanın ofsetini döndürür.

Bir video karesinin kodunu şu şekilde çözeriz:

const getFrameFromVideoDecoder = async (demuxer: any): Promiseany> => {
let desiredSampleIndex = demuxer.getFrameIndexForTimestamp(this.frameTime);
let timestampToMatch: number;
let decodedSample: VideoFrame | null = null;

const outputCallback = (frame: VideoFrame) => {
if (frame.timestamp === timestampToMatch) decodedSample = frame;
else frame.close();
};

const decoder = new VideoDecoder({
output: outputCallback,
});
const {
codec,
codecWidth,
codecHeight,
description,
} = demuxer.getDecoderConfigurationInfo();
decoder.configure({ codec, codecWidth, codecHeight, description });

/* begin demuxer interface */
const preceedingKeyFrameIndex = demuxer.getPreceedingKeyFrameIndex(
desiredSampleIndex
);
const trak_id = demuxer.trak_id
const trak = demuxer.moov.traks.find((trak: any) => trak.tkhd.track_id === trak_id);
const data = await demuxer.getFrameDataRange(
preceedingKeyFrameIndex,
desiredSampleIndex
);
/* end demuxer interface */

for (let i = preceedingKeyFrameIndex; i desiredSampleIndex; i += 1) {
const sample = trak.samples[i];
const sampleData = data.readNBytes(
sample.offset,
sample.size
);

const sampleType = sample.is_sync ? 'key' : 'delta';
const encodedFrame = new EncodedVideoChunk({
sampleType,
timestamp: sample.cts,
duration: sample.duration,
samapleData,
});

if (i === desiredSampleIndex)
timestampToMatch = encodedFrame.timestamp;
decoder.decodeEncodedFrame(encodedFrame, i);
}
await decoder.flush();

return { type: 'value', value: decodedSample };
};

Demuxer’ın yapısı oldukça karmaşıktır ve bu makalenin kapsamı dışındadır. Her çerçeveyi başlıklı bir dizide saklar. samples. Video kodunu çözmeye başlamamız gereken yer olan, istediğimiz zaman damgasına en yakın önceki anahtar kareyi bulmak için demuxer’ı kullanırız.

Videolar, anahtar veya i-kareler olarak bilinen tam kareler ile genellikle p- veya b-kareler olarak adlandırılan çok daha küçük delta karelerden oluşur. Kod çözme her zaman bir anahtar karede başlamalıdır.

Uygulama, çerçevelerin kodunu şu şekilde çözer:

  1. Bir çerçeve çıktısı geri araması ile kod çözücünün somutlaştırılması.
  2. Kod çözücüyü belirli codec bileşeni ve giriş çözünürlüğü için yapılandırma.
  3. oluşturma encodedVideoChunk demuxer’dan gelen verileri kullanarak.
  4. arama decodeEncodedFrame yöntem.

Bunu, istenen zaman damgasına sahip kareye ulaşana kadar yapıyoruz.

Sıradaki ne? #

Ön ucumuzda ölçeği, projeler büyüdükçe ve karmaşıklaştıkça hassas ve performanslı oynatmayı sürdürme yeteneği olarak tanımlıyoruz. Performansı ölçeklendirmenin bir yolu, aynı anda mümkün olduğunca az video yüklemektir, ancak bunu yaptığımızda, yavaş ve kesik kesik geçişler riskiyle karşı karşıya kalırız. Video bileşenlerini yeniden kullanım için önbelleğe almak üzere dahili sistemler geliştirmiş olsak da, HTML5 video etiketlerinin sağlayabileceği kontrol konusunda sınırlamalar vardır.

Gelecekte, WebCodec’leri kullanarak tüm ortamları oynatmayı deneyebiliriz. Bu, performansı ölçeklendirmeye yardımcı olması gereken hangi verileri arabelleğe aldığımız konusunda çok kesin olmamızı sağlayabilir.

Ayrıca, büyük izleme dörtgeni hesaplamalarını web çalışanlarına aktarma konusunda daha iyi bir iş çıkarabiliriz ve dosyaları önceden getirme ve çerçeveleri önceden oluşturma konusunda daha akıllı olabiliriz. Genel uygulama performansımızı optimize etmek ve işlevselliği aşağıdakiler gibi araçlarla genişletmek için büyük fırsatlar görüyoruz: WebGL.

yatırımlarımıza devam etmek istiyoruz. TensorFlow.js, şu anda akıllı arka plan kaldırma için kullanıyoruz. Nesne algılama, özellik çıkarma, stil aktarımı vb. gibi diğer karmaşık görevler için TensorFlow.js’den yararlanmayı planlıyoruz.

Sonuç olarak, ürünümüzü yerel performans ve işlevsellik ile ücretsiz ve açık bir web üzerinde oluşturmaya devam etmekten heyecan duyuyoruz.

İlgili Mesajlar

Yorum eklemek için giriş yapmalısınız.