Como usar o VLC para assistir a um arquivo (enquanto ele está sendo modificado) em um servidor SSH (usando sftp ou smth else)?

1

Estou usando meu servidor ssh para gravar vídeos e gostaria de assisti-los (em um PC usando o Windows 7 ou 8) durante a gravação. É claro que posso transferir o arquivo quando terminar e assisti-lo, mas quero assisti-lo durante a gravação, que pode durar 2 horas.

Eu não quero usar um servidor VLC porque ele codifica o vídeo e meu servidor SSH está em um Odroid C1 (não poderoso o suficiente para isso eu acho), e eu perderia alguma qualidade.

Eu vi aqui algumas idéias VLC: Posso transmitir via SSH? mas isso não é suficiente.

Eu já pensei em 2 ângulos aqui:

  • Encontrar uma maneira de baixar o arquivo "indefinidamente": o que significa que, enquanto o arquivo estiver ficando maior, o download continuará. Mas eu não sei se isso é possível, eu tentei o WinSCP, mas o download termina mesmo achando que o arquivo está constantemente atualizando.
  • Transmitindo o arquivo com algo parecido no VLC "sftp: ///", mas não sei como configurar a conexão com o VLC (minha conexão SSH não está na porta 22 e eu uso chaves públicas / privadas).

Alguém tem alguma ideia?

    
por Syl 17.03.2015 / 15:12

1 resposta

2

Como todas as minhas tentativas de transmitir diretamente com o VLC com um link "sftp: //" falharam, consegui escrever um pequeno programa java que faria exatamente o que eu precisava baixando o arquivo e sempre verificando se o tamanho o arquivo remoto foi alterado para continuar o download, se necessário.

A chave aqui é esse pedaço de código:

    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.");

Eu também estou postando todo o código do programa se alguém estiver interessado:

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);
        }
    }
}
    
por 26.03.2015 / 10:38