我正在使用 ssh 服务器录制视频,并且希望能够在录制过程中观看它们(在使用 Windows 7 或 8 的 PC 上)。当然,我可以在完成后传输文件并观看,但我想在录制过程中观看它,这可能会持续 2 个小时。
我不想使用 VLC 服务器,因为它会对视频进行编码,而我的 SSH 服务器位于 Odroid C1 上(我认为它不够强大),这会损失一些质量。
我在这里看到了一些想法VLC:我可以通过 SSH 进行流式传输吗?但这还不够。
我在这里考虑了两个角度:
- 找到一种“无限期”下载文件的方法:这意味着只要文件越来越大,下载就会继续。但我不知道这是否可行,我试过 WinSCP,但即使文件在不断更新,下载也会结束。
- 在 VLC“sftp:///”中使用类似这样的命令来流式传输文件,但我不知道如何配置与 VLC 的连接(我的 SSH 连接不在端口 22 上,并且我使用公钥/私钥)。
有人有什么想法吗?
答案1
由于我所有使用“sftp://”链接直接使用 VLC 进行流式传输的尝试都失败了,因此我设法编写了一个小型 Java 程序,该程序可以完全按照我的需要下载文件,并始终检查远程文件的大小是否已更改,以便在需要时恢复下载。
这里的关键是那段代码:
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.");
如果有人感兴趣的话我还会发布该程序的完整代码:
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);
}
}
}