Secure WebM MPEG-DASH streams using Common Encryption in Wowza Streaming Engine

Learn how to configure encryption for WebM MPEG-DASH streams using the Common Encryption (CENC) standard with Wowza Streaming Engine™ media server software. This article assumes you're sending a WebM compatible VP8/VP9 stream directly to Wowza Streaming Engine. You can also use Transcoder to generate the VP8/VP9 stream. The examples in this article use the default Wowza Streaming Engine live application and a live WebM stream named myStream.

Note: Wowza Streaming Engine 4.4.0 or later is required.
  1. Configure the default live application in Wowza Streaming Engine for MPEG-DASH streaming. For configuration instructions, see Stream over MPEG-DASH with Wowza Streaming Engine.
  2. Add the following custom module that injects DRM information into the WebM live stream. See Use custom modules for information about how to add custom modules.
     
    import com.wowza.wms.drm.cenc.*;
    import com.wowza.wms.module.*;
    import com.wowza.wms.stream.livepacketizer.*;
    
    public class ModuleWebMDashEncryption extends ModuleBase
    {
        public static class WebMDashCustomDRMInfo implements ICencDRMInfo
        {
            String systemName = null;
            String systemId = null;
            String url = null;
    
            public WebMDashCustomDRMInfo(String systemName)
            {
                this.systemName = systemName;
            }
    
            @Override
            public void setSystemId(String systemId)
            {
                this.systemId = systemId;
            }
    
            @Override
            public String getSystemId()
            {
                return systemId;
            }
    
            @Override
            public String getURL()
            {
                return url;
            }
    
            @Override
            public void setURL(String url)
            {
                this.url = url;
            }
    
            @Override
            public String getNameSpaces()
            {
                return null;
            }
    
            @Override
            public String getMPEGDashCPSubElements(boolean keyRotation)
            {
                return null;
            }
    
            @Override
            public String getSystemName()
            {
                return this.systemName;
            }
    
            @Override
            public boolean supportsKeyGeneration()
            {
                return false;
            }
    
            @Override
            public byte[] generateKey(byte[] KID)
            {
                return null;
            }
    
            @Override
            public void updateKeyInfo(byte[] KID, byte[] contentKey)
            {
            }
    
            @Override
            public byte[] serialize()
            {
                return null;
            }
    
            @Override
            public void deserialize(byte[] data)
            {
            }
    
            @Override
            public byte[] getPsshData(boolean keyRotation)
            {
                return null;
            }
    
            @Override
            public void setPsshData(byte[] psshData)
            {
            }
    
            @Override
            public boolean isComplete()
            {
                return true;
            }
        }
    
        public void onHTTPMPEGDashEncryptionKeyLiveChunk(ILiveStreamPacketizer liveStreamPacketizer, String streamName, CencInfo cencInfo, long chunkId)
        {
            if (cencInfo.getKID() != null && cencInfo.getEncKeyString() != null)
            {
                try
                {
                    String idStr = "test";
                    String url = "empty";
                    String systemId = "12345678-1234-1234-1234-123456789012";
    
                    WebMDashCustomDRMInfo drmInfo = new WebMDashCustomDRMInfo(idStr);
    
                    drmInfo.setURL(url);
                    drmInfo.setSystemId(systemId);
    
                    getLogger().info("ModuleWebMDashEncryption.onHTTPMPEGDashEncryptionKeyLiveChunk["+streamName+"]: Add DRM: "+idStr+":"+systemId);
                    cencInfo.addDRM(idStr+":"+systemId, drmInfo);
                    cencInfo.setKeyRotationType(CencInfo.KEY_ROTATION_TYPE_NONE);
                    cencInfo.setPSSHVersion(CencInfo.PSSH_VERSION_1);
                }
                catch (Exception e)
                {
                    getLogger().error("ModuleWebMDashEncryption.onHTTPMPEGDashEncryptionKeyLiveChunk["+streamName+"]: ", e);
                }
            }
        }
    }
  3. Add a key file named [install-dir]/keys/myStream.key to encrypt the live stream.
     
    mpegdashstreaming-cenc-key-id: 12345DCF-7F93-4B8E-85C7-F908840DA059
    mpegdashstreaming-cenc-content-key: Hh8gISIjJCUmJx4fICEiIw==
    mpegdashstreaming-cenc-algorithm: AESCTR
    mpegdashstreaming-cenc-pssh-version: 1
  4. Send a WebM-compatible live stream named myStream to the live application in Wowza Streaming Engine. You should see a log statement similar to the following that indicates the stream is being encrypted:

    MPEGDashWriterHandler.createChunkWebM[live/_definst_/myStream]: WebM encryption: kid:12345dcf7f934b8e85c7f908840da059
     
  5. Play the stream using a player that supports WebM MPEG-DASH encryption like Google Shaka Player. Refer to the documentation for your player for information about configuring playback of encrypted WebM MPEG-DASH streams.

More resources