rectangle_device_sandbox/
ffmpeg.rs

1use std::error::Error;
2use async_process::{Stdio, Child};
3use crate::runtime;
4use crate::socket::SocketPool;
5use crate::types::ImageDigest;
6
7pub fn default_image() -> ImageDigest {
8    // Video transcoder image to use. This should be replaced with a locally preferred image
9    // as well as a list of acceptable images that we'll be happy to run if we are trying to
10    // reproduce a particular video block which requests it.
11    // Also see: https://ffmpeg.org/security.html
12    // Seems we want a combination of approaches, using a very restrictive sandbox plus
13    // whitelisting versions of ffmpeg. As a result, videos that were uploaded using older
14    // versions of ffmpeg may not find servers willing to re-run those transcodes if needed.
15
16    ImageDigest::parse(
17        "docker.io/jrottenberg/ffmpeg:4.3.1-scratch38",
18        "68126e39534eff79a8a4a4b7b546a11b8165a1ee8f1af93166d3071b170280a1"
19    ).unwrap()
20}
21
22#[derive(Clone, Debug)]
23pub struct TranscodeConfig {
24    pub image: ImageDigest,
25    pub args: Vec<String>,
26    pub allow_networking: bool,
27    pub segment_time: f32,
28}
29
30pub async fn start(tc: TranscodeConfig, pool: &SocketPool) -> Result<Child, Box<dyn Error>> {
31
32    if !runtime::image_exists(&tc.image).await? {
33        runtime::pull(&tc.image).await?;
34    }
35
36    // Be specific about sandbox options
37    let mut command = runtime::command();
38    command
39        .arg("run")
40        .arg("--rm")
41        .arg("--attach=stdout")
42        .arg("--attach=stderr")
43        .arg("--env-host=false")
44        .arg("--read-only")
45        .arg("--restart=no")
46        .arg("--detach=false")
47        .arg("--privileged=false");
48
49    if tc.allow_networking {
50        command
51            .arg("--net=slirp4netns")
52            .arg("--dns-search=.");
53    } else {
54        command.arg("--net=none");
55    }
56
57    command
58        .args(&pool.mount_args)
59        .arg(tc.image.digest.as_str())
60        .args(tc.args);
61
62    // Additional args for ffmpeg
63
64    command
65        .arg("-nostats")
66        .arg("-nostdin")
67        .arg("-loglevel").arg("error")
68        .arg("-f").arg("stream_segment")
69        .arg("-segment_format").arg("mpegts")
70        .arg("-segment_wrap").arg("1")
71        .arg("-segment_time").arg(tc.segment_time.to_string())
72        .arg("unix:///out/%d.ts");
73
74    log::info!("starting, {:?}", command);
75
76    Ok(command
77        .stdout(Stdio::inherit())
78        .stderr(Stdio::inherit())
79        .spawn()?)
80}