How to use VLC to watch a file (while it is being modified) on a SSH server (using sftp or smth else)?
Since all my attempts to stream directly with VLC with a "sftp://" link failed, I managed to write a little java program that would do exactly what I needed by downloading the file and by always checking if the size of the remote file has changed to resume the download if needed.
The key here is that piece of code:
sftpChannel.get(remotePath, outstream, monitor, ChannelSftp.OVERWRITE, 0);
long localSize;
Thread.sleep(1000);
while(sftpChannel.lstat(remotePath).getSize() > (localSize = new File(localPath).length())){
sftpChannel.get(remotePath, outstream, monitor, ChannelSftp.RESUME, localSize);
Thread.sleep(timeToWaitBeforeUpdatingFile);
}
System.out.println("The download is finished.");
I'm also posting the whole code for the program if someone is interested:
package streamer;
import java.io.Console;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Scanner;
import java.util.Vector;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.SftpProgressMonitor;
public class Streamer {
public static void main(String[] args) throws InterruptedException, IOException {
JSch jsch = new JSch();
if(args.length != 7){
System.out.println("Incorrect parameters:");
System.out.println("Streamer user host port privateKeyPath remotePath localPath vlcPath");
System.exit(-1);
}
String user = args[0];
String host = args[1];
int port = -1;
try {
port = Integer.parseInt(args[2]);
} catch (NumberFormatException e3) {
System.out.println("Port must be an integer");
System.exit(-1);
}
String privateKeyPath = args[3];
String remotePath = args[4];
String localPath = args[5];
String vlcPath = args[6];
int timeToWaitBeforeUpdatingFile = 5000;
String password = "";
Console console = System.console();
if (console == null) {
System.out.println("Couldn't get Console instance");
//password = "";
System.exit(-1);
}else{
char passwordArray[] = console.readPassword("Enter your password: ");
password = new String(passwordArray);
Arrays.fill(passwordArray, ' ');
}
try {
jsch.addIdentity(privateKeyPath, password);
} catch (JSchException e) {
System.out.println(e.getMessage());
System.out.println("Invalid private key file");
System.exit(-1);
}
Session session;
try {
session = jsch.getSession(user, host, port);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
System.out.println("Establishing connection...");
session.connect();
System.out.println("Connection established.");
System.out.println("Creating SFTP Channel...");
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
System.out.println("SFTP Channel created.");
try {
@SuppressWarnings("unchecked")
Vector<ChannelSftp.LsEntry> recordings = sftpChannel.ls(remotePath + "*.mpeg");
if(recordings.isEmpty()){
System.out.println("There are no recordings to watch.");
System.exit(0);
}
int choice = 1;
System.out.println("Chose the recording to watch:");
for (ChannelSftp.LsEntry e : recordings){
System.out.println("[" + choice++ + "] " + e.getFilename());
}
Scanner sc = new Scanner(System.in);
try {
String fileName = recordings.get(sc.nextInt() - 1).getFilename();
remotePath += fileName;
localPath += fileName;
} catch (InputMismatchException e) {
System.out.println("Incorrect choice");
System.exit(-1);
}
System.out.println("You chose : " + remotePath);
sc.close();
} catch (SftpException e2) {
System.out.println("Error during 'ls': the remote path might be wrong:");
System.out.println(e2.getMessage());
System.exit(-1);
}
OutputStream outstream = null;
try {
outstream = new FileOutputStream(new File(localPath));
} catch (FileNotFoundException e) {
System.out.println("The creation of the file" + localPath + " failed. Local path is incorrect or writing permission is denied.");
System.exit(-1);
}
try {
SftpProgressMonitor monitor = null;
System.out.println("The download has started.");
System.out.println("Opening the file in VLC...");
try {
Runtime.getRuntime().exec(vlcPath + " " + localPath);
} catch (Exception ex) {
System.out.println("The file couldn't be opened in VLC");
System.out.println("Check your VLC path.");
System.out.println(ex);
}
sftpChannel.get(remotePath, outstream, monitor, ChannelSftp.OVERWRITE, 0);
long localSize;
Thread.sleep(1000);
while(sftpChannel.lstat(remotePath).getSize() > (localSize = new File(localPath).length())){
sftpChannel.get(remotePath, outstream, monitor, ChannelSftp.RESUME, localSize);
Thread.sleep(timeToWaitBeforeUpdatingFile);
}
System.out.println("The download is finished.");
outstream.close();
System.exit(0);
} catch (SftpException e1) {
System.out.println("Error during the download:");
System.out.println(e1.getMessage());
System.exit(-1);
}
} catch (JSchException e) {
System.out.println("Connection has failed (check the user, host, port...)");
System.exit(-1);
}
}
}