直播软件源码如何实现直播flash插件

项目搭建

原有的项目是用的layui+jq搭建。现在将大屏部分独立出来;

开心到飞起,哈哈哈

现在大屏单独出来做,我采用了react + react-mobx;

选用react的原因是,对react比较熟练

选用mobx的原因是,项目内容比较简单,没有涉及到负责的数据处理

项目遇到的坑

<object id="plugin1" type="application/x-deepcam-p2p">
<param name="onload" value="pluginLoaded" />
</object>
复制代码

flash部分,完全脱离文档流,独立的窗口。不可以在上面定位任何的图标。这就导致很多功能无法去实现。

flash容易卡死在网页上,当用户频繁操作时。

flash视频音量的控制,实际上是控制整个计算机系统的音量,并不能像音乐播放器只控制单独的应用。

具体的实现

  • 一页大屏的适配

先来一个控制大屏占满全局的组件BaseComponent

class BaseComponent extends Component {
constructor(props) {
super(props);
this.state = {
...super.state,
screenWidth: props.width || -1,
screenHeight: props.height || -1,
topHeight: -1
};
}
resizeScreen() {
try {
const parentDom = ReactDOM.findDOMNode(this).parentNode;
let {
width,
height,
topHeight
} = this.props;
if (!width) {
width = parentDom.offsetWidth;
}
if (!height) {
height = (width * global.settings.standardHeight) / global.settings.standardWidth;
}
if (!topHeight && height) {
topHeight = (height * 120) / global.settings.standardHeight;
}
global.settings.screenHeight = height;
global.settings.screenWidth = width;
this.setState({
screenWidth: width,
screenHeight: height
})
} catch (ignore) {
// debugger;
}
}

scaleHeight(height, unit) {
return (height * global.settings.screenHeight) / global.settings.standardHeight + (unit ? unit : 0);
}

scaleWidth(width, unit) {
return (width * global.settings.screenWidth) / global.settings.standardWidth + (unit ? unit : 0);
}
}

export default BaseComponent;
//config.js
global.settings = {
screenWidth: 1408,
screenHeight: 768,
standardWidth: 1920, //设计图宽度
standardHeight: 1080, //设计图宽度
}
复制代码

这样就可以适配 浏览器了,在入口组件App.js中;

let timer;
let flag = false;

class App extends BaseComponent {
constructor(props) {
super(props);
this.state = {
width: this.state.screenWidth,
height: this.state.screenHeight,
showPage: false
}
}

componentDidMount() {
this.resizeScreen();
window.addEventListener('resize',this.handleResize();
}

handleResize = () => {
if (flag) {
clearTimeout(timer);
timer = setTimeout(() => {
this.resizeScreen();
// window.location.reload();
flag = false;
}, 100)
} else {
flag = true;
timer = setTimeout(() => {
this.resizeScreen();
// window.location.reload();
flag = false;
}, 100)
}
}

componentWillUnmount() {
window.removeEventListener('resize',this.handleResize);
}

render() {
const {store} = this.props;
return (
this.state.showPage ?
<div style={{marginTop: this.returnMarginByScreenRatio(),position: 'relative'}}>
<Header/>
<div style={{
width: this.scaleWidth(1920, 'px'),
height: this.scaleHeight(686, 'px')
}}>
</div> : ''
);
}
}

export default App;
复制代码
  • 使用插件部分

直接调用flash的api播放,

let flag = true;

@inject('store')
@observer
class MyVideo extends React.Component {

handleChangePlugin = ({ uuid, channel_id, pasword, username }) => {
setTimeout(() => {
const plugin = document.getElementById('plugin0');
if (plugin.valid) {
plugin.set_volume(0);
let ret = plugin.connect_camera1(uuid, username, pasword, channel_id, 1);
if (ret < 0) {
console.log("connect camera err");
}
} else {
console.log("Plugin is not working :(");
}
})
}

handleStopPlugin = () => {
const plugin = document.getElementById('plugin0');
if (plugin.valid) {
plugin.disconnect_all_camera();
}
}

handleChangePluginVoice = (voice) => {
const plugin = document.getElementById('plugin0');
if (plugin.valid) {
plugin.set_volume(voice);
}
}

handleChangePluginFour = ([{ uuid, pasword, username }], nPage) => {
setTimeout(() => {
const plugin = document.getElementById('plugin0');
if (plugin.valid) {
let ret = plugin.connect_camera4(uuid, username, pasword, 2, nPage);
if (ret < 0) {
console.log("connect camera err" + ret);
}
}
});
}

componentDidMount() {
const plugin = document.getElementById('plugin1');
const flag1 = plugin && !plugin.valid;
this.props.store.handleToClose(
flag1
);
}

shouldComponentUpdate(nextProps) {
if (!nextProps.flag1) {
if(!nextProps.isVideo) {
this.props.store.handleChangeIsVideo();
if (nextProps.channel_num === 1) {
this.handleChangePlugin(nextProps.data[0]);
}
else {
this.handleChangePluginFour(nextProps.data, nextProps.nPage);
}
}
if (nextProps.data.length === 0) {
this.handleStopPlugin();
}
if (nextProps.data.length > 0 && ((nextProps.data.length !== this.props.data.length && flag) ||
(this.props.data[0] && this.props.data[0].name !== nextProps.data[0].name))) {
flag = false;
if (nextProps.channel_num === 1) {
this.handleChangePlugin(nextProps.data[0]);
}
else {
this.handleChangePluginFour(nextProps.data, nextProps.nPage);
}
}
if (nextProps.voiceFlag !== this.props.voiceFlag || nextProps.voice !== this.props.voice) {
this.handleChangePluginVoice(nextProps.voiceFlag ? nextProps.voice : 0);
}
if (nextProps.channel_num !== this.props.channel_num && nextProps.data.length > 0) {
if (nextProps.channel_num === 1) {
this.handleChangePlugin(nextProps.data[0]);
}
else {
this.handleChangePluginFour(nextProps.data, nextProps.nPage);
}
}
if (nextProps.nPage !== this.props.nPage && nextProps.channel_num === 4) {
this.handleChangePluginFour(nextProps.data, nextProps.nPage);
}
return nextProps.flag1 !== this.props.flag1 || nextProps.nPage !== this.props.nPage || nextProps.uuiD !== this.props.uuiD || (nextProps.channel_num !== this.props.channel_num && nextProps.data.length > 0)
|| nextProps.voiceFlag !== this.props.voiceFlag || (nextProps.voice !== this.props.voice ||
!!(nextProps.data.length > 0 && ((nextProps.data.length !== this.props.data.length && flag) ||
(this.props.data[0] && this.props.data[0].name !== nextProps.data[0].name)))
);
} else {
return false;
}
}

render() {
const { store, data, voice, voiceFlag, channel_num, uuiD, nPage, flag1 } = this.props;
return <MyVideoBox>
<object id="plugin1" type="application/x-deepcam-p2p" style={{
width: 0,
height: 0,
display: 'none'
}}>
<param style={{
width: 0,
height: 0,
display: 'none'
}} name="onload" value="pluginLoaded" />
</object>
<OneV id="plugin0" style={{ display: flag1 ? 'none' : 'block' }} type="application/x-deepcam-p2p">
<param name="onload" value="pluginLoaded" />
</OneV>
{!flag1 ? '' :
<XiaZhai>
<Header>
<div className="my-close" onClick={() => {
store.handleToClose(false)
}}></div>
<img src={require('./ic_tips.png')} alt='' />&nbsp;&nbsp;点击下载&nbsp;<span onClick={() => {
store.handleToClose(false)
}}><a download href="/static/templateFile/deepcam.exe">播放插件</a></span>,推荐使用IE浏览器播放
</Header>
<Content></Content>
</XiaZhai>}
<Process />
<Onechannel onClick={() => { store.handleChangeChannelNum(1) }} src={channel_num === 4 ? OnechannelBg : OnechannelBgH} />
<Fourchannel onClick={() => { store.handleChangeChannelNum(4) }} src={channel_num === 4 ? FourchannelBgH : FourchannelBg} />
{data.length > 0 && channel_num === 1 ? <Title>{data[0].name}</Title> : ''}
{channel_num === 1 ? <VoiceBox>
<Slider tooltipPlacement='right' value={voice} onChange={(e) => { store.handleChangeVoice(e) }} />
</VoiceBox> : ''}
{channel_num === 1 ? <VoiceIcon src={voiceFlag ? VoiceBg : VoiceBgN} onClick={store.handleChangeVoiceFlag} /> : ''}
<BeforeBtn src={channel_num === 1 ?
store.devicePage === 0 ? BeforeBtnBg : BeforeBtnBgH :
nPage === 0 ? BeforeBtnBg : BeforeBtnBgH
} onClick={channel_num === 1 ? () => {
store.handleChangeUuid('before');
} : () => {
store.handleChangeNPage('before');
}} />
<NextBtn src={channel_num === 1 ?
store.allDevice.length === 0 || store.allDevice.length === 1
|| store.devicePage + 1 >= store.allDevice.length ? NextBtnBgH : NextBtnBg :
uuiD === 0 || uuiD === 1
|| (nPage + 1) * 4 >= uuiD ? NextBtnBgH : NextBtnBg
}
onClick={channel_num === 1 ? () => {
store.handleChangeUuid('next');
} : () => {
store.handleChangeNPage('next');
}} />
</MyVideoBox>
}
};

export default MyVideo;

还用一个点,怎么判断有没有安装flash控件。直接判断object对象有没有valid即可。

直播软件源码如何实现直播flash插件本文转载自网络,感谢(马毛画唐卡)的分享