How to integrate wavesurfer with existing audio - React - reactjs

I have an audio element that is being used in multiple other components to play songs. I would like to integrate wavesurfer to this already existing audio. This issue https://github.com/katspaugh/wavesurfer.js/issues/986 says I can load the audio tag, but I get errors when doing it. I believe it's because my audio component is actually of type ForwardRefExoticComponent<Props & RefAttributes<HTMLAudioElement>> instead of just an HTMLAudioElement
const WavesurferComponent = (props: Props) => {
const { isPlaying } = props;
const [waver, setWaver] = useState<MODWaveSurfer | null>(null);
const waveformRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!waveformRef.current) return;
const modedWaveSurfer = WaveSurfer as unknown as MODWaveSurfer;
const wavesurfer = modedWaveSurfer.create({
barWidth: 3,
container: waveformRef.current,
backend: 'WebAudio',
height: 30,
barRadius: 3,
responsive: true,
progressColor: ['#26D1A8', '#AC4EFD', '#F1419E', '#FED503', '#FE5540'],
waveColor: '#1C1B1B',
barGap: 3,
cursorColor: 'transparent',
});
wavesurfer.load(AudioElement);
setWaver(wavesurfer);
return () => wavesurfer.destroy();
}, []);
useEffect(() => {
if (isPlaying && waver) waver.playPause();
}, [isPlaying]);
return (
<div>
<div ref={waveformRef} style={{ width: '225px', margin: '0 auto' }} />
</div>
);
};
// AUDIO ELEMENT
export const AudioElement = forwardRef<HTMLAudioElement, Props>((props, ref) => {
const { className } = props;
return <audio ref={ref} className={className} />;
});

Related

Why everyone can mute anyone even after there is a moderator?

I am creating a video meet interface in react using '#jitsi/react-sdk'.When a room is created then even after there is a moderator everyone is able to mute anyone why is it happening.
Here is the code:
import { JitsiMeeting } from '#jitsi/react-sdk';
import React, { useRef, useState } from 'react';
const App = () => {
const apiRef = useRef();
const [logItems, updateLog] = useState([]);
const [users, setUsers] = useState([])
const [knockingParticipants, updateKnockingParticipants] = useState([]);
const addParticipants = payload => {
setUsers(items => [...items, payload]);
}
const removeParticipants = payload => {
setUsers(participants => participants.filter(item => item.id !== payload.id));
}
const printEventOutput = payload => {
updateLog(items => [...items, JSON.stringify(payload)]);
};
const handleAudioStatusChange = (payload, feature) => {
if (payload.muted) {
updateLog(items => [...items, `${feature} off`])
} else {
updateLog(items => [...items, `${feature} on`])
}
};
const handleChatUpdates = payload => {
if (payload.isOpen || !payload.unreadCount) {
return;
}
apiRef.current.executeCommand('toggleChat');
updateLog(items => [...items, `you have ${payload.unreadCount} unread messages`])
};
const handleKnockingParticipant = payload => {
updateLog(items => [...items, JSON.stringify(payload)]);
updateKnockingParticipants(participants => [...participants, payload?.participant])
};
const handleJitsiIFrameRef1 = iframeRef => {
iframeRef.style.border = '10px solid #3d3d3d';
iframeRef.style.background = '#3d3d3d';
iframeRef.style.height = '400px';
};
const handleApiReady = apiObj => {
apiRef.current = apiObj;
apiRef.current.on('knockingParticipant', handleKnockingParticipant);
apiRef.current.on('audioMuteStatusChanged', payload => handleAudioStatusChange(payload, 'audio'));
apiRef.current.on('videoMuteStatusChanged', payload => handleAudioStatusChange(payload, 'video'));
apiRef.current.on('raiseHandUpdated', printEventOutput);
apiRef.current.on('titleViewChanged', printEventOutput);
apiRef.current.on('chatUpdated', handleChatUpdates);
apiRef.current.on('knockingParticipant', handleKnockingParticipant);
apiRef.current.on('participantJoined', addParticipants);
apiRef.current.on('participantKickedOut', removeParticipants);
apiRef.current.on('participantLeft', removeParticipants);
};
const handleReadyToClose = () => {
/* eslint-disable-next-line no-alert */
alert('Ready to close...');
};
const generateRoomName = () => `JitsiMeetRoomNo${Math.random() * 100}-${Date.now()}`;
const renderSpinner = () => (
<div style={{
fontFamily: 'sans-serif',
textAlign: 'center'
}}>
Loading..
</div>
);
return (
<>
<h1 style={{
fontFamily: 'sans-serif',
textAlign: 'center'
}}>
JitsiMeeting App
</h1>
<JitsiMeeting
roomName={generateRoomName()}
spinner={renderSpinner}
configOverwrite={{
startWithAudioMuted: true,
startWithVideoMuted: true,
}}
config={{
hideConferenceSubject: false
}}
onApiReady={externalApi => handleApiReady(externalApi)}
onReadyToClose={handleReadyToClose}
getIFrameRef={handleJitsiIFrameRef1} />
</>
);
};
export default App;
Can anyone tell me what am I doing wrong and roundabout to get the feature implemented where only moderator can mute the mic and camera of other participants.

my react state variable is not updating while using websocket

hello I'm using websocket to get my data, the problem is that when i tried to save the data into my state in react component is re rendering as expected but my data is not saved on state variable
export default function ResultPageContent() {
const processed = useSelector((state) => state.processedSlice);
const [data, setData] = useState({});
const fetchData = (links) => {
const socket = new webSocket("ws://localhost:5000/");
socket.onopen = () => {
socket.send(JSON.stringify(links));
};
socket.onmessage = ({ data }) => {
const tempData = JSON.parse(data);
setData(tempData);
};
socket.onclose = () => {};
};
const renderContent = () => {
if (data.per < 100) {
return <CircularProgressWithLabel value={data.per} />;
}
};
if (processed) {
console.log("links", links);
fetchData(links);
dispatch(MAKE_FALSE());
}
return (
<div>
<Paper
style={{
width: "100%",
background: theme.palette.background.default,
marginBottom: "50px",
}}
className={classes.root}
>
{renderContent()}
</Paper>
</div>
);
}```

want to give average height to wave in wavesurfer

import React, { useEffect, useRef, useState } from "react";
import WaveSurfer from "wavesurfer.js";
const formWaveSurferOptions = ref => ({
container: ref,
barWidth:1,
waveColor: "#eee",
progressColor: "OrangeRed",
cursorColor: "OrangeRed",
barRadius: 10,
responsive: true,
height: 200,
barGap:0,
pixelRatio: 5,
barMinHeight:100,
normalize: true,
partialRender: true
});
export default function Waveform({ url }) {
const waveformRef = useRef(null);
const wavesurfer = useRef(null);
const [playing, setPlay] = useState(false);
const [volume, setVolume] = useState(0.5);
useEffect(() => {
setPlay(false);
const options = formWaveSurferOptions(waveformRef.current);
wavesurfer.current = WaveSurfer.create(options);
wavesurfer.current.load(url);
wavesurfer.current.on("ready", function() {
if (wavesurfer.current) {
wavesurfer.current.setVolume(volume);
setVolume(volume);
}
});
return () => wavesurfer.current.destroy();
}, [url]);
const handlePlayPause = () => {
...
};
const onVolumeChange = e => {
...
};
return (
<div>
<div id="waveform" ref={waveformRef} />
<div className="controls">
<button onClick={handlePlayPause}>{!playing ? "Play" : "Pause"}</button>
<input
...
/>
<label htmlFor="volume">Volume</label>
</div>
</div>
);
}
The problem in this is that, i want to set the height of the minpeak of the wave and also give the height an average that at this level it does not go up. i tried the minHeightBar, but unfortunatelydoes't work at all, I have connected the two images for better understanding, so if any one knows this so please help, thankyou :)

how to add a classList in react using material UI

I'm trying to add a class to an element using Material UI in a scroll event like this.
const useStyles = makeStyles({
sticky: {
position: 'fixed',
top: 0,
width: '100%',
}
});
export default function myBar() {
React.useEffect(() => {
const myBar = document.getElementById("myBar");
const sticky = myBar.offsetTop;
const scrolling = window.addEventListener("scroll", () => {
if (window.pageYOffset > sticky) {
myBar.classList.add("sticky");
} else {
myBar.classList.remove("sticky");
}
});
return () => {
window.removeEventListener("scroll", scrolling);
};
}, []);
const classes = useStyles();
return (
<header id="myBar">
// some content
</header>
);
};
The problem is that Mterial Ui will generate some random numbers after class name, like sticky_123 so it will never be only sticky
Is it any way I can solve this problem?
The problem is that Material Ui will generate some random numbers after class name, like sticky_123 so it will never be only sticky
In order to use the className generated by Material UI, you must use classes.sticky instead of "sticky".
By the way, the component name should be in PascalCase.
const useStyles = makeStyles({
sticky: {
position: 'fixed',
top: 0,
width: '100%',
}
});
export default function MyBar() {
const classes = useStyles();
useEffect(() => {
const myBar = document.getElementById("myBar");
const sticky = myBar.offsetTop;
const scrollHandler = () => {
if (window.pageYOffset > sticky) {
myBar.classList.add(classes.sticky);
} else {
myBar.classList.remove(classes.sticky);
}
};
window.addEventListener("scroll", scrollHandler)
return () => {
window.removeEventListener("scroll", scrollHandler);
};
}, [classes]);
return (
<header id="myBar">
// some content
</header>
);
};

react-native: How to create custom component dynamically and destroy it after use?

I am creating a screen in functional component where I have to execute an animation when there is any event occurs ... This event could occur 1000 times when screen is open ... so I have implemented a custom component which takes position on screen and animates ....
const FloatingComponent = (props) => {
const animationView = useSharedValue(1)
const animationOpacityView = useSharedValue(1)
const animationViewStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: withTiming(animationView.value, {
duration: 3500
}),
}
],
opacity: withTiming(animationOpacityView.value, {
duration: 1500
})
}
})
useEffect(() => {
console.log('Component animation called')
animationView.value = -((Screen.width * 0.25))
animationOpacityView.value = 0
});
return (
<Animated.View style={[Styles.handImg, { top: props.topDistance }, animationViewStyle]}>
<Image
style={Styles.handImage}
source={require('../../../assets/images/hand.png')}
/>
</Animated.View>
);
};
To create it dynamically I implemented it like this
const driverFactory = (itemNumber) => {
console.log(itemNumber)
return (<FloatingComponent id={1} topDistance={(Screen.width * 0.25) * itemNumber} />);
};
but it never show up and executes ....
while if I add this
<FloatingDriver id={5} topDistance={(Screen.width * 0.25) * 6} />
to main screen return it always executes .... but by these I can not create n number of components at any time when i receive notification ...
I would have a parent component manage these n child components and their rendering. Here is an example showing how one might render all the components with animations and handle showing/removing them as needed.
import React from 'react';
import {Animated, Button, SafeAreaView, StyleSheet} from 'react-native';
const Particle = ({particle: {x, y}, onFinish}) => {
const opacity = React.useRef(new Animated.Value(0)).current;
React.useEffect(() => {
Animated.timing(opacity, {
toValue: 1,
duration: 2000,
useNativeDriver: true,
}).start(() => {
onFinish();
});
}, []);
return (
<Animated.View
style={{
position: 'absolute',
left: x - 10,
bottom: y - 10,
width: 20,
height: 20,
backgroundColor: 'yellow',
opacity,
}}
/>
);
};
const ParticleSystem = () => {
const [layoutRectangle, setLayoutRectangle] = React.useState();
const [particleList, setParticleList] = React.useState([]);
const currentRef = React.useRef();
const addRandomParticle = React.useCallback(() => {
if (layoutRectangle) {
const newParticle = {
id: Math.floor(Math.random() * Number.MAX_SAFE_INTEGER),
x: Math.random() * layoutRectangle.width,
y: Math.random() * layoutRectangle.height,
};
setParticleList([newParticle, ...particleList]);
}
}, [layoutRectangle, particleList]);
const removeParticle = React.useCallback(
(particle) => {
setParticleList(particleList.filter(({id}) => id !== particle.id));
},
[particleList],
);
currentRef.current = removeParticle;
return (
<SafeAreaView
style={styles.screen}
onLayout={(event) => setLayoutRectangle(event.nativeEvent.layout)}>
{particleList.map((particle) => (
<Particle
key={particle.id}
particle={particle}
onFinish={() => {
currentRef.current(particle);
}}
/>
))}
<Button title="Add particle" onPress={() => addRandomParticle()} />
</SafeAreaView>
);
};
export default ParticleSystem;
const styles = StyleSheet.create({
screen: {
flex: 1,
backgroundColor: 'black',
},
});

Resources