Search Results for

    Show / Hide Table of Contents

    Set up a LiveSwitch Vue Project

    This tutorial demonstrates how to add video streaming to a Vue app using the LiveSwitch Web SDK.

    Prerequisites

    Before you begin, you must have done the following:

    • Installed node.js and npm
    • Added an application in the LiveSwitch Console and got the Application ID and Shared Secret for your application

    Create a Vue App

    Create a new Vue app using the Vue CLI.

    1. Install the Vue CLI if you haven't done so.

      npm install -g @vue/cli
      
    2. In the terminal, find a location on your drive where you want to create the project and run the following command to create a Vue app named my-app. You can modify these presets as needed to suit your requirements.

      vue create --inlinePreset='{ "useConfigFiles": false, "plugins": { "@vue/cli-plugin-babel": {}, "@vue/cli-plugin-eslint": { "config": "base", "lintOn": ["save"] } }, "router": true, "routerHistoryMode": true }' my-app
      

    Install the LiveSwitch Web SDK

    To install the LiveSwitch Web SDK, do the following:

    1. Go to the project directory.

      cd my-app
      
    2. Install the LiveSwitch Client SDK.

      npm install fm.liveswitch  
      

    Create a LiveSwitch Vue Plugin

    The best way to work with the asynchronous methods of the LiveSwitch SDK is to create a reusable bridge (plugin) between LiveSwitch and Vue. The following steps describe how to accomplish this:

    1. Inside the src folder, create a new folder called liveswitch.

    2. Create a new file named index.js. In this file, import the LiveSwitch Web SDK to the project and create logic to stream video. For information about how to generate an authorization token, register a client to a channel and stream media, see Media Streaming Basics. The completed file should look like the following:

      import Vue from 'vue'
      import ls from 'fm.liveswitch'
      
      let instance
      
      export const getInstance = () => instance
      
      export const useLiveSwitch = ({
      
        applicationId = '-specify-in-liveswitch_config.json',
        token = '',
        gatewayUrl = '-specify-in-liveswitch_config.json',
        // callback for when your local camera/mic are up and running
        onLocalMediaReady = function () {},
        // callback for when a user joins
        onParticipantJoin = function () {},
        // callback for when a user leaves
        onParticipantLeave = function () {}
      
        /// ...options
      }) => {
        if (instance) return instance
      
        // The 'instance' is simply a Vue object
        instance = new Vue({
          data () {
            return {
      
            }
          },
          methods: {
            async startStreaming () {
              const promise = new ls.Promise()
              try {
                this.client = new ls.Client(gatewayUrl, applicationId)
                this.connectionRecords = {}
      
                const channels = await this.client.register(token)
      
                // we auto-joined one channel, so just use that one
                this.channel = channels[0]
      
                // start local media - camera/microphone
                const media = new ls.LocalMedia(true, true)
                await media.start()
                onLocalMediaReady(media)
      
                // open a connection up to the server
                this.openUpstreamConnection(this.channel, media)
      
                // listen for other remote participants to open a connection
                this.channel.addOnRemoteUpstreamConnectionOpen((remoteConnectionInfo) => {
                  this.addConnection(remoteConnectionInfo)
                })
                // for connections that already exist when we joined, join them
                this.channel.getRemoteUpstreamConnectionInfos().forEach(remoteConnectionInfo => {
                  this.addConnection(remoteConnectionInfo)
                })
      
                promise.resolve(null)
              } catch (ex) {
                promise.reject(ex)
              }
              return promise
            },
            openUpstreamConnection (channel, localMedia) {
              const audioStream = (localMedia.getAudioTrack() != null) ? new ls.AudioStream(localMedia) : null
              const videoStream = (localMedia.getVideoTrack() != null) ? new ls.VideoStream(localMedia) : null
              const connection = channel.createSfuUpstreamConnection(audioStream, videoStream)
      
              connection.addOnStateChange(conn => {
                if (conn.getState() === ls.ConnectionState.Failed) {
                  this.openUpstreamConnection(channel, localMedia)
                }
              })
              connection.open()
              return connection
            },
            async stopStreaming () {
              const promise = new ls.Promise()
              try {
                await this.removeConnections()
                await this.client.unregister()
                promise.resolve(null)
              } catch (ex) {
                promise.reject(ex)
              }
              return promise
            },
            async addConnection (info) {
              let promise = new ls.Promise()
              try {
                // create a remote media/view for the downstream
                const media = new ls.RemoteMedia()
                const video = new ls.VideoStream(null, media)
      
                // create the connection
                const connection = this.channel.createSfuDownstreamConnection(info, video)
      
                // store some metadata with the connection
                const record = {
                  id: info.getClientId(),
                  media: media,
                  video: video,
                  connection: connection
                }
                this.connectionRecords[connection.getId()] = record
      
                // hook up some events
                connection.addOnStateChange((c) => {
                  switch (c.getState()) {
                    case ls.ConnectionState.Connected:
                      onParticipantJoin(record)
                      break
                    case ls.ConnectionState.Closed:
                    case ls.ConnectionState.Failed:
                      this.removeConnection(record)
                      onParticipantLeave(record)
                      break
                  }
                })
      
                // open the connection
                promise = connection.open()
              } catch (ex) {
                console.error(ex)
                promise.reject(ex)
              }
              return promise
            },
            async removeConnections () {
              const promises = []
              for (const [, record] of Object.entries(this.connectionRecords)) {
                promises.push(this.removeConnection(record))
              }
              return Promise.all(promises)
            },
            async removeConnection (record) {
              let promise = new ls.Promise()
              try {
                promise = record.connection.close()
                delete this.connectionRecords[record.connection.getId()]
              } catch (ex) {
                promise.reject(ex)
              }
              return promise
            }
          },
          async created () {
            this.startStreaming()
          }
        })
      
        return instance
      }
      
      export const LiveSwitchPlugin = {
        install (Vue, options) {
          Vue.prototype.$liveswitch = useLiveSwitch(options)
        }
      }
      
    3. In the root directory of your app alongside your package.json file, create a new file called liveswitch_config.json.

    4. Add the following content and replace with your own Application ID and Shared Secret. If you use your own LiveSwitch Server, replace the Gateway URL. This information is used for generating an authorization token.

      {
          "applicationId": "replace-with-your-app-id",
          "gatewayUrl" : "https://cloud.liveswitch.io", 
          "channelId": "/room/1",
          "sharedSecret": "replace-with-your-shared-secret"
      }
      
    5. To render the video feeds, append the following to the <style> block in App.vue:

      video {
          width: auto;
          height: auto;
          position: relative;
      }
      
      Note

      For your production app, you should use the LayoutManager class. It dynamically manages the video elements to maximize the space on the page for video feeds.

    Install and Use the Plugin

    Finally, open src/main.js and use Vue.use to install the plugin. To do this, pass the following properties into the plugin:

    • The token that was generated using the configuration file
    • Three callbacks: one for your local camera, the other two for when a user joins or leaves
    • Your Application ID

    LiveSwitch imports the configuration file created earlier to initialize the plugin, and generate a token using that information. By taking this approach, your Shared Secret is never exposed to the outside world, and you can restrict access based on your requirements.

    1. Update the src/main.js file with the following:

      import Vue from 'vue'
      import App from './App.vue'
      import router from './router'
      import ls from 'fm.liveswitch'
      
      // Import the LiveSwitch configuration
      import { applicationId, channelId, sharedSecret } from '../liveswitch_config.json'
      
      // Import the plugin
      import { LiveSwitchPlugin } from './liveswitch'
      
      Vue.config.productionTip = false
      
      // generate a token that will let us connect to the server
      // we use the values from the config here
      // Never generate tokens on the client side in a production application
      const token = ls.Token.generateClientRegisterToken(applicationId, null, null, null, null, [new ls.ChannelClaim(channelId)], sharedSecret)
      
      // a few handlers
      // in your production application, these handlers should
      // store the media/record objects in a reactive VueX store
      // where all your sub-components can access/react to them
      const onLocalMediaReady = function (media) {
        const home = document.getElementsByClassName('home')[0]
        home.insertBefore(media.getView(), home.firstChild)
      }
      
      const onParticipantJoin = function (record) {
        const home = document.getElementsByClassName('home')[0]
        home.insertBefore(record.media.getView(), home.firstChild)
      }
      
      const onParticipantLeave = function (record) {
        const home = document.getElementsByClassName('home')[0]
        home.removeChild(record.media.getView())
      }
      
      // Install the LiveSwitch plugin
      Vue.use(LiveSwitchPlugin, {
        applicationId,
        token,
        onLocalMediaReady,
        onParticipantJoin,
        onParticipantLeave
      })
      
      // normal vue stuff
      new Vue({
        router,
        render: h => h(App)
      }).$mount('#app')
      
    2. Run the app:

      npm run serve
      

    For the complete example app that this page describes, check out this GitHub repository.

    In This Article
    Back to top Copyright © LiveSwitch Inc. All Rights Reserved.Documentation for LiveSwitch Version 1.6.2