Wowza Community

My encoder can't connect to my EC2 instance of Wowza

EDIT: It’s definitely my module:

Local - Wowza Streaming Engine 4.1.0, Windows 8, Java version 1.7.0_67

Server - The Wowza Streaming Engine AMI here. Java version 1.7.0_65

I have Wowza running locally and on an EC2 instance.

Locally it works fine and I can connect and publish streams to my application without a problem. I cannot connect or publish streams to the application on my server, however.

I removed the .jar (module) that went with the application, and I was able to connect and publish to my app, though it gave me a warning that it couldn’t find the associated module, which was to be expected.

I put the module back in, restarted the server, and I was unable to connect.

It appears that my .jar file is stopping the application from loading for some reason.

Here’s the source for my module:

package com.xxxxxxxxxxxxxxx.recorder;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.S3ClientOptions;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.wowza.wms.application.*;
import com.wowza.wms.amf.*;
import com.wowza.wms.client.*;
import com.wowza.wms.module.*;
import com.wowza.wms.request.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.rtp.model.*;
import com.wowza.wms.httpstreamer.model.*;
import com.wowza.wms.httpstreamer.cupertinostreaming.httpstreamer.*;
import com.wowza.wms.httpstreamer.smoothstreaming.httpstreamer.*;
public class RecorderModules extends ModuleBase implements AWSCredentialsProvider {
    IApplicationInstance appInstance;
    private String videoBucket;
    private String thumbBucket;
    private String videoDistro;
    private String thumbnailDistro;
    private String region;
    private AmazonS3Client s3;
    private String dir;
    public void onAppStart(IApplicationInstance appInstance) {
        String fullname = appInstance.getApplication().getName() + "/"
                + appInstance.getName();
        getLogger().info("onAppStart: " + fullname);
        this.appInstance = appInstance;
        try{
            videoBucket = appInstance.getProperties().getPropertyStr("videoBucket");
            getLogger().info("Video bucket is " + videoBucket);
            thumbBucket = appInstance.getProperties().getPropertyStr("thumbBucket");
            getLogger().info("Thumb bucket is " + thumbBucket);
            videoDistro = appInstance.getProperties().getPropertyStr("videoDistro");
            getLogger().info("Video distro is " + videoDistro);
            thumbnailDistro =appInstance.getProperties().getPropertyStr("thumbnailDistro");
            getLogger().info("thumbnail distro is " + thumbnailDistro);
            region = appInstance.getProperties().getPropertyStr("region");
            getLogger().info("region is " + region);
            s3 = new AmazonS3Client();
            s3.setEndpoint(region);
            getLogger().info("AmazonS3Client is created");
        }catch(Exception e){
            getLogger().info("Could not read config " + e);
        }
    }
    public void doSave(IClient client, RequestFunction function, AMFDataList params) {
        getLogger().info("doSave hit ");
        new File(dir + params.getString(3) + ".flv").renameTo(new File(dir+params.getString(4)+".flv"));
        getLogger().info("Starting upload");
        String thumbName = params.getString(4).replace("vid_", "thumb_")+".jpg";
        String flvName = params.getString(4)+".flv";
        String mp4Name = params.getString(4)+".mp4";
        try{
            PutObjectRequest p = new PutObjectRequest(videoBucket,flvName, new File(dir+flvName));
            p.setRequestCredentials(getCredentials());
            p.setCannedAcl(CannedAccessControlList.BucketOwnerFullControl);
            getLogger().info("attempting to upload " + flvName + " to " + videoBucket);
            s3.putObject(p);
            getLogger().info("flv upload complete " + videoBucket + " " + flvName);
            PutObjectRequest p2 = new PutObjectRequest(thumbBucket,thumbName, new File(dir+thumbName));
            p2.setRequestCredentials(getCredentials());
            p2.setCannedAcl(CannedAccessControlList.PublicRead);
            getLogger().info("attempting to upload " + thumbName + " to " + thumbBucket);
            s3.putObject(p2);
            getLogger().info("thumb upload complete " + thumbBucket + " " + thumbName);
            String[] info = new String[5];
            info[0] =  videoDistro+params.getString(4);
            info[1] = thumbnailDistro+thumbName;
            info[2] = params.getString(4);
            info[3] = videoBucket;
            info[4] = thumbBucket;
            getLogger().info("sending info to client " + info[0]);
            //client.call("uploadDone", null,(Object[])info);
        }catch(Exception e){
            getLogger().info("Upload failed");
            getLogger().info(e);
            //client.call("uploadFailed")
        }
        //transcode
        //-crf 23 -refs 3 -profile:v baseline -level 3.0 -pix_fmt yuv420p -preset veryslow
        String[] command = {"ffmpeg",
                "-i", dir+params.getString(4)+".flv",
                "-crf", "23",
                "-refs","3",
                "-profile:v","baseline",
                "-level","3.0",
                "-pix_fmt","yuv420p",
                "-preset","veryslow",
                dir+params.getString(4)+".mp4"};
        try { 
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true);
            getLogger().info("Starting process");
            Process process = builder.start();
            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = null;
            while((line = in.readLine()) != null) {
              System.out.println(line);
            }
            process.waitFor();
            PutObjectRequest p = new PutObjectRequest(videoBucket,mp4Name, new File(dir+mp4Name));
            p.setRequestCredentials(getCredentials());
            p.setCannedAcl(CannedAccessControlList.BucketOwnerFullControl);
            getLogger().info("transcoding completed");
            s3.putObject(p);
            getLogger().info("mp4 file uploaded");
        } catch (Exception e) {
            getLogger().info("Error running ffmpeg");
            e.printStackTrace();
        }
        deleteFiles(params.getString(4).replace("vid_",""));
    }
    public void saveThumbnail(IClient client, RequestFunction function, AMFDataList params){
        String dir = client.getAppInstance().getStreamStoragePath()+"/"+"thumb_"+params.getString(4).split(",")[2]+".jpg";
        getLogger().info(params);
        Path path = Paths.get(dir);
        byte[] byteArr = (byte[])((AMFDataByteArray)params.get(3)).getValue();
        try {
            Files.write(path, byteArr, StandardOpenOption.CREATE_NEW);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void onAppStop(IApplicationInstance appInstance) {
        String fullname = appInstance.getApplication().getName() + "/"
                + appInstance.getName();
        getLogger().info("onAppStop: " + fullname);
    }
    public void onConnect(IClient client, RequestFunction function, AMFDataList params) {
        getLogger().info("onConnect: " + client.getClientId());
    }
    public void onConnectAccept(IClient client) {
        getLogger().info("onConnectAccept: " + client.getClientId());
    }
    public void onConnectReject(IClient client) {
        getLogger().info("onConnectReject: " + client.getClientId());
    }
    public void onDisconnect(IClient client) {
        getLogger().info("onDisconnect: " + client.getClientId());
    }
    public void onStreamCreate(IMediaStream stream) { 
        getLogger().info("onStreamCreate: " + stream.getSrc());
    }
    public void onStreamDestroy(IMediaStream stream) {
        getLogger().info("onStreamDestroy: " + stream.getSrc());
    }
    public void onHTTPSessionCreate(IHTTPStreamerSession httpSession) {
        getLogger().info("onHTTPSessionCreate: " + httpSession.getSessionId());
    }
    public void onHTTPSessionDestroy(IHTTPStreamerSession httpSession) {
        getLogger().info("onHTTPSessionDestroy: " + httpSession.getSessionId());
    }
    public void onHTTPCupertinoStreamingSessionCreate(HTTPStreamerSessionCupertino httpSession) {
        getLogger().info(
                "onHTTPCupertinoStreamingSessionCreate: "
                        + httpSession.getSessionId());
    }
    public void onHTTPCupertinoStreamingSessionDestroy(HTTPStreamerSessionCupertino httpSession) {
        getLogger().info(
                "onHTTPCupertinoStreamingSessionDestroy: "
                        + httpSession.getSessionId());
    }
    public void onHTTPSmoothStreamingSessionCreate( HTTPStreamerSessionSmoothStreamer httpSession) {
        getLogger().info(
                "onHTTPSmoothStreamingSessionCreate: "
                        + httpSession.getSessionId());
    }
    public void onHTTPSmoothStreamingSessionDestroy( HTTPStreamerSessionSmoothStreamer httpSession) {
        getLogger().info(
                "onHTTPSmoothStreamingSessionDestroy: "
                        + httpSession.getSessionId());
    }
    public void onRTPSessionCreate(RTPSession rtpSession) {
        getLogger().info("onRTPSessionCreate: " + rtpSession.getSessionId());
    }
    public void onRTPSessionDestroy(RTPSession rtpSession) {
        getLogger().info("onRTPSessionDestroy: " + rtpSession.getSessionId());
    }
    public void onCall(String handlerName, IClient client, RequestFunction function, AMFDataList params) {
        getLogger().info("onCall: " + handlerName);
    }
    /* Overwritten method: Delete content of the same name before starting */
    public void publish(IClient client, RequestFunction function, AMFDataList params) {
        getLogger().info("publish hit");
        String name = params.getString(3).replace("flv:","").replace("vid_","").replace("_temp", "");
        getLogger().info("name:" + name);
        dir = appInstance.decodeStorageDir("${com.wowza.wms.AppHome}"+"/content/recorder/");
        deleteFiles(name);
        invokePrevious(client,function,params);
    }
    private void deleteFiles(String name){
        getLogger().info("deleting " + name);
        try {
            if(Files.exists(Paths.get(dir+"thumb_"+name+".jpg"))){
                getLogger().info("deleting  thumbnail");
                Files.delete(Paths.get(dir+"thumb_"+name+".jpg"));
            }
            if(Files.exists((Paths.get(dir+"vid_"+name+".flv")))){
                getLogger().info("deleting  video");
                Files.delete(Paths.get(dir+"vid_"+name+".flv"));
            }
            if(Files.exists((Paths.get(dir+"vid_"+name+".mp4")))){
                getLogger().info("deleting  mp4 video");
                Files.delete(Paths.get(dir+"vid_"+name+".mp4"));
            }
            if(Files.exists((Paths.get(dir+"vid_"+name+"_temp.flv")))){
                getLogger().info("deleting  temp video");
                Files.delete(Paths.get(dir+"vid_"+name+"_temp.flv"));
            }
        } catch (IOException e) {
            getLogger().info("Could not delete old files");
        }
    }
    @Override
    public AWSCredentials getCredentials() {
        getLogger().info("getting credentials");
        return new BasicAWSCredentials(appInstance.getProperties().getPropertyStr("accessKey"),appInstance.getProperties().getPropertyStr("secretKey"));
    }
    @Override
    public void refresh() {
        // TODO Auto-generated method stub
    }
}

It might be related to this:

When I try and combine all my dependencies (the aws libs) into the module, I get an error message that says “Module class not found or could not be loaded.”

When I don’t try and combine anything, the module completely, and silently, fails to load.

Hi there,

This is usually caused by the encoder not sending the application name properly.

Check that the application name is specified and is not mis-spelled or malformed.

Thank you.

Salvadore

It would be most helpful if in the future, you please add new information and details as new posts in the thread as opposed to editing existing posts. This will keep the conversation more understandable and vital information will be more easily accessible. Sometimes folks don’t always re-read the original post.

A few things to try would be to check if you have a typo in the /conf/[app-name]/Application.xml /Modules RecorderModules Module, or confirm that the jar file is located in the Wowza /lib folder, also be sure you have restarted Wowza since adding the jar file.

Salvadore

Cool, thanks for the update and glad to hear you got this working.

Salvadore

The application name that the encoder is sending exactly matches the application name on the server manager.

This would probably be easier if the java modules had error logs that were independent of the wowza logs.

I don’t think I have any typos in the Application.xml.

The jar file is located in the lib directory

I have restarted Wowza since adding the jar file.

If I had typos in my Application.xml, it would ALWAYS return that “Class not found or could not be loaded” error, but it doesn’t. If I upload the .jar without trying to package the dependencies in the archive, I do not get that error message.

When running wowza with startup.sh I get this when my application tries to load:

Exception in thread "ServerHandler.12" java.lang.NoClassDefFoundError: com/amazonaws/auth/AWSCredentialsProvider
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:190)
        at com.wowza.wms.util.ModuleUtils.addModuleToApp(ModuleUtils.java:32)
        at com.wowza.wms.util.ApplicationUtils.a(ApplicationUtils.java:183)
        at com.wowza.wms.util.ApplicationUtils.loadConfigFile(ApplicationUtils.java:321)
        at com.wowza.wms.application.ApplicationInstance.a(ApplicationInstance.java:646)
        at com.wowza.wms.application.ApplicationInstance.<init>(ApplicationInstance.java:269)
        at com.wowza.wms.application.Application.getAppInstance(Application.java:569)
        at com.wowza.wms.module.ModuleConnect.connect(ModuleConnect.java:1072)
        at com.wowza.wms.request.RequestProcessFunctions.processFunctions(RequestProcessFunctions.java:89)
        at com.wowza.wms.request.RequestProcessData.flushFunction(RequestProcessData.java:58)
        at com.wowza.wms.request.RequestProcessData.processNextRequest(RequestProcessData.java:852)
        at com.wowza.wms.request.RTMPRequestAdapter.service(RTMPRequestAdapter.java:570)
        at com.wowza.wms.server.ServerHandler.a(ServerHandler.java:653)
        at com.wowza.wms.server.ServerHandler.a(ServerHandler.java:375)
        at com.wowza.wms.server.ServerHandler.messageReceived(ServerHandler.java:487)
        at com.wowza.wms.server.ServerHandlerThreadedSession.run(ServerHandlerThreadedSession.java:108)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.amazonaws.auth.AWSCredentialsProvider
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        ... 31 more

This is from using the .jar without attempting to include the dependencies in the archive.

I resolved it by installing everything differently on a new server.

I took by auto-generated .jar file, and the two jar files that it depended on, commons-codec-1.9 and aws-java-sdk-1.4.7, and installed them using the “startup package” method.

And everything worked fine.