欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:js錄制音頻

柚子快報激活碼778899分享:js錄制音頻

http://yzkb.51969.com/

整體思路

1、監(jiān)聽用戶onTouchStart事件,設置一個定時器記錄是否長按,然后調用JSBridge開始錄制事件 2、通過JSBridge監(jiān)聽錄音過程,拿到錄音的數據,前端用數組變量存放 3、監(jiān)聽用戶onTouchEnd松開事件,清除定時器,處理錄音數組轉換成一個文件上傳到oss

難點

難點一:將base64錄音片段轉為WAV文件 首先將一系列Base64編碼的音頻段合并成一個PCM數據流; 然后創(chuàng)建一個WAV文件的頭部信息; 最后合并WAV文件頭和PCM數據

難點二:TypedArray數據的合并 TypedArray: 存儲的是固定類型的數值數據,如整數或浮點數。 Array: 可以存儲任何類型的數據,包括數字、字符串、對象等

開始錄音

/**

* 開始錄音

*/

const handleTouchStart = (event) => {

event.preventDefault();

timerId = setTimeout(() => {

setLongPress(true);

console.log('handleTouchStart 長按了');

JSBridge(XX.startRecording', {

numberOfChannels: 1, // 聲道數

// sampleRate: 16000, // 采樣率

sampleRate: 44100, // 更改采樣率為 44100 Hz

bitsPerChannel: 16, // 位深

format: 'PCM',

}).then(() => {

setRecordStatus('dialog_listening');

});

}, 100); // 長按時長,這里設置為100ms

};

監(jiān)聽錄音過程

const onRecordChange = (event) => {

console.log(event);

const { error, param } = event || {};

const { pcm } = param || {};

const { errorCode, errorMsg } = error || {};

if (errorCode) {

Toast.show({

type: 'error',

content: `錄制失敗,${errorMsg}`,

});

baseArrayRef.current = [];

} else {

baseArrayRef.current.push(pcm);

}

};

useEffect(() => {

document.addEventListener('RecordingDataBufferTransfer', onRecordChange);

return () => {

// 清除長按定時器

if (timerId !== null) clearTimeout(timerId);

};

}, []);

結束錄制

/**

* 結束錄音

* @returns

*/

const handleTouchEnd = (event) => {

if (timerId !== null) {

clearTimeout(timerId)

timerId = null

}

if (!longPress) return;

setLongPress(false);

console.log('handleTouchEnd 松開了');

JSBridge('XX.stopRecording').then(() => {

// 移除事件監(jiān)聽器

document.removeEventListener(

'RecordingDataBufferTransfer',

onRecordChange,

);

setRecordStatus('dialog_sleep');

onMerge();

});

};

音頻波動動畫

VoiceAnimation/index.tsx

import cls from 'classnames';

import debounce from 'lodash/debounce';

import { useLayoutEffect, useMemo, useRef } from 'react';

import styles from './index.module.less';

interface IProps {

status: string;

}

export default function (props: IProps) {

const { status = 'dialog_sleep' } = props;

const list = useMemo(() => new Array(5).fill(true), []);

return (

{list.map((_, index) => (

))}

);

}

function getTransationByStatus(status: string, index?) {

return {

dialog_sleep: {

transition: 'all 0.3s',

height: '8px',

transform: 'translateY(0)',

},

dialog_idle: {

transition: 'all 0.3s',

height: '8px',

transform: 'translateY(0)',

},

dialog_listening: {

transition: 'all 0.3s',

height: '24px',

transform: index % 2 ? 'translateY(8px)' : 'translateY(-8px)',

onTransitionEnd: debounce(

(event) => {

if (

event.target.parentElement.className.indexOf('dialog_listening') ===

-1

)

return;

event.target.style.transitionDuration = '0.5s';

event.target.style.height = '24px';

event.target.style.transform =

event.target.style.transform === 'translateY(8px)'

? 'translateY(-8px)'

: 'translateY(8px)';

},

{

leading: true,

trailing: false,

},

),

},

dialog_thinking: {

transition: 'all 0.3s',

height: `${[52, 44, 36, 28, 24][index]}px`,

transform: 'translateY(0)',

onTransitionEnd: debounce(

(event) => {

if (

event.target.parentElement.className.indexOf('dialog_thinking') ===

-1

)

return;

event.target.style.transitionDuration = '0.5s';

event.target.style.height = {

'52px': '24px',

'44px': '28px',

'36px': '32px',

'32px': '36px',

'28px': '44px',

'24px': '52px',

}[event.target.style.height];

},

{

leading: true,

trailing: false,

},

),

},

dialog_responding: {

transition: 'all 0.2s',

height: `${Math.random() * (index + 1) * 10 + 24}px`,

transform: 'translateY(0)',

onTransitionEnd: debounce(

(event) => {

if (

event.target.parentElement.className.indexOf(

'dialog_responding',

) === -1

)

return;

event.target.style.transitionDuration = '0.15s';

event.target.style.height = `${Math.random() * (index + 1) * 10 + 24}px`;

},

{

leading: true,

trailing: false,

},

),

},

}[status];

}

function AnimationItem({ status, index }: { status: string; index?: number }) {

const div = useRef();

useLayoutEffect(() => {

const container = div.current as HTMLDivElement;

function reset() {

container.ontransitionend = (e) => {};

container.style.transition = 'all .1s';

container.style.height = '24px';

container.style.transform = 'translateY(0)';

}

reset();

const { onTransitionEnd = () => {}, ...style } =

getTransationByStatus(status, index) || {};

container.ontransitionend = onTransitionEnd;

for (let prop in style) {

container.style[prop] = style[prop];

}

return () => {};

}, [status]);

return (

);

}

VoiceAnimation/index.module.less

.voice {

display: flex;

justify-content: center;

align-items: center;

height: 56px;

.item {

// width: 24px;

// height: 24px;

background-color: var(--TY-Text-Brand-1);

border-radius: 20px;

margin: 0 4px;

transform: translateY(0);

}

}

.loop(@n, @i: 0) when (@i <= @n) {

&:nth-child(@{i}) {

animation-delay: (@i * 0.2s);

}

.loop(@n, (@i + 1));

}

一個完整的音頻錄制——播放的例子

pcmtowav

getUserMedia需要https,使用localhost或127.0.0.1時,可用http。

柚子快報激活碼778899分享:js錄制音頻

http://yzkb.51969.com/

好文推薦

評論可見,查看隱藏內容

本文內容根據網絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉載請注明,如有侵權,聯系刪除。

本文鏈接:http://gantiao.com.cn/post/19512389.html

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄