diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 20f1cab4..36e971e7 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -8,10 +8,22 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - - run: rustup update stable - - run: rustup component add rustfmt - - run: rustup component add clippy - - run: cargo test --all-features - - run: cargo fmt --all -- --check - - run: cargo clippy --all-features --all-targets -- --deny warnings - - run: cargo build --all-features + - name: On all Systems + run: | + rustup update stable + rustup component add rustfmt + rustup component add clippy + + - name: Use ffmpeg on Linux + if: ${{ matrix.os == 'ubuntu-latest' }} + uses: FedericoCarboni/setup-ffmpeg@v1 + + - name: Tests on Linux + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + cargo test --all-features + cargo clippy --all-features --all-targets -- --deny warnings + cargo fmt --all -- --check + + - name: Run build on all Systems + run: cargo build --all-features diff --git a/Cargo.lock b/Cargo.lock index 96ae70e8..faacf2db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,7 +16,7 @@ dependencies = [ "memchr", "pin-project-lite", "tokio", - "tokio-util 0.7.3", + "tokio-util 0.7.4", ] [[package]] @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.2.1" +version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f9ffb6db08c1c3a1f4aef540f1a63193adc73c4fbd40b75a95fc8c5258f6e51" +checksum = "0c83abf9903e1f0ad9973cc4f7b9767fd5a03a583f51a5b7a339e07987cd2724" dependencies = [ "actix-codec", "actix-rt", @@ -120,16 +120,15 @@ dependencies = [ [[package]] name = "actix-router" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb60846b52c118f2f04a56cc90880a274271c489b2498623d58176f8ca21fa80" +checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" dependencies = [ "bytestring", - "firestorm", "http", - "log", "regex", "serde", + "tracing", ] [[package]] @@ -183,9 +182,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.1.0" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27e8fe9ba4ae613c21f677c2cfaf0696c3744030c6f485b34634e502d6bb379" +checksum = "d48f7b6534e06c7bfc72ee91db7917d4af6afe23e7d223b51e68fffbb21e96b9" dependencies = [ "actix-codec", "actix-http", @@ -205,6 +204,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", + "http", "itoa", "language-tags", "log", @@ -217,15 +217,15 @@ dependencies = [ "serde_urlencoded", "smallvec", "socket2", - "time 0.3.14", + "time 0.3.15", "url", ] [[package]] name = "actix-web-codegen" -version = "4.0.1" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f270541caec49c15673b0af0e9a00143421ad4f118d2df7edcb68b627632f56" +checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13" dependencies = [ "actix-router", "proc-macro2", @@ -277,24 +277,24 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] [[package]] name = "alloc-no-stdlib" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" dependencies = [ "alloc-no-stdlib", ] @@ -377,9 +377,9 @@ dependencies = [ [[package]] name = "async-io" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab006897723d9352f63e2b13047177c3982d8d79709d713ce7747a8f19fd1b0" +checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" dependencies = [ "autocfg", "concurrent-queue", @@ -522,9 +522,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -644,9 +644,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.18" +version = "3.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15f2ea93df33549dbe2e8eecd1ca55269d63ae0b3ba1f55db030817d1c2867f" +checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" dependencies = [ "atty", "bitflags", @@ -681,6 +681,16 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "concurrent-queue" version = "1.2.4" @@ -698,12 +708,12 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "cookie" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" dependencies = [ "percent-encoding", - "time 0.3.14", + "time 0.3.15", "version_check", ] @@ -725,9 +735,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -778,12 +788,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if 1.0.0", - "once_cell", ] [[package]] @@ -807,14 +816,59 @@ dependencies = [ ] [[package]] -name = "dashmap" -version = "5.3.4" +name = "cxx" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" +checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dashmap" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if 1.0.0", "hashbrown", "lock_api", + "once_cell", "parking_lot_core 0.9.3", ] @@ -833,9 +887,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ "block-buffer", "crypto-common", @@ -864,9 +918,9 @@ dependencies = [ [[package]] name = "dotenvy" -version = "0.15.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3db6fcad7c1fc4abdd99bf5276a4db30d6a819127903a709ed41e5ff016e84" +checksum = "ed9155c8f4dc55c7470ae9da3f63c6785245093b3f6aeb0f5bf2e968efbba314" dependencies = [ "dirs", ] @@ -902,17 +956,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "enum-primitive-derive" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e" -dependencies = [ - "num-traits", - "quote", - "syn", -] - [[package]] name = "event-listener" version = "2.5.3" @@ -941,7 +984,7 @@ dependencies = [ [[package]] name = "ffplayout" -version = "0.15.2" +version = "0.16.0" dependencies = [ "chrono", "clap", @@ -951,6 +994,7 @@ dependencies = [ "jsonrpc-http-server", "notify", "openssl", + "regex", "reqwest", "serde", "serde_json", @@ -960,7 +1004,7 @@ dependencies = [ [[package]] name = "ffplayout-api" -version = "0.6.2" +version = "0.7.0" dependencies = [ "actix-files", "actix-multipart", @@ -990,7 +1034,7 @@ dependencies = [ [[package]] name = "ffplayout-lib" -version = "0.15.2" +version = "0.16.0" dependencies = [ "chrono", "crossbeam-channel", @@ -1009,16 +1053,16 @@ dependencies = [ "serde_yaml", "shlex", "simplelog", - "time 0.3.14", + "time 0.3.15", "walkdir", "winapi 0.3.9", ] [[package]] name = "ffprobe" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4151d364a3709c400c4aaca1988324f02dfde8d3e2e8543176e596d39eb414ac" +checksum = "b5d603974ab029fc75cebf00bfa06c9c6f49a6fb657f4f5f6a9fd6cbd76910a4" dependencies = [ "serde", "serde_json", @@ -1046,12 +1090,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "firestorm" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5f6c2c942da57e2aaaa84b8a521489486f14e75e7fa91dab70aba913975f98" - [[package]] name = "flate2" version = "1.0.24" @@ -1097,11 +1135,10 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] @@ -1316,7 +1353,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.3", + "tokio-util 0.7.4", "tracing", ] @@ -1331,9 +1368,9 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452c155cb93fecdfb02a73dd57b5d8e442c2063bd7aac72f1bc5e4263a43086" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" dependencies = [ "hashbrown", ] @@ -1403,9 +1440,9 @@ checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -1452,18 +1489,28 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.47" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" +checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" dependencies = [ "android_system_properties", "core-foundation-sys", + "iana-time-zone-haiku", "js-sys", - "once_cell", "wasm-bindgen", "winapi 0.3.9", ] +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "idna" version = "0.2.3" @@ -1475,6 +1522,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "1.9.1" @@ -1531,33 +1588,33 @@ checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1675,7 +1732,7 @@ dependencies = [ "futures-util", "hostname", "httpdate", - "idna", + "idna 0.2.3", "mime", "native-tls", "nom", @@ -1686,9 +1743,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.132" +version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" [[package]] name = "libsqlite3-sys" @@ -1701,6 +1758,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1727,9 +1793,9 @@ checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" [[package]] name = "lock_api" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -1787,9 +1853,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] @@ -1957,15 +2023,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "openssl" -version = "0.10.41" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -2004,9 +2070,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.75" +version = "0.9.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" dependencies = [ "autocfg", "cc", @@ -2095,9 +2161,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "pem" @@ -2110,9 +2176,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pin-project" @@ -2198,9 +2264,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ "unicode-ident", ] @@ -2243,9 +2309,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -2304,9 +2370,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ "base64", "bytes", @@ -2320,10 +2386,10 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", "pin-project-lite", "serde", @@ -2416,6 +2482,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "security-framework" version = "2.7.0" @@ -2441,24 +2513,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "serde" -version = "1.0.144" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -2467,9 +2539,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074" dependencies = [ "itoa", "ryu", @@ -2502,9 +2574,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -2513,9 +2585,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -2546,7 +2618,7 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.14", + "time 0.3.15", ] [[package]] @@ -2558,7 +2630,7 @@ dependencies = [ "log", "paris", "termcolor", - "time 0.3.14", + "time 0.3.15", ] [[package]] @@ -2572,15 +2644,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c98bba371b9b22a71a9414e420f92ddeb2369239af08200816169d5e2dd7aa" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi 0.3.9", @@ -2603,9 +2675,9 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.1.8" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" +checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" dependencies = [ "itertools", "nom", @@ -2614,9 +2686,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "788841def501aabde58d3666fcea11351ec3962e6ea75dbcd05c84a71d68bcd1" +checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" dependencies = [ "sqlx-core", "sqlx-macros", @@ -2624,9 +2696,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c21d3b5e7cadfe9ba7cdc1295f72cc556c750b4419c27c219c0693198901f8e" +checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" dependencies = [ "ahash", "atoi", @@ -2667,9 +2739,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4adfd2df3557bddd3b91377fc7893e8fa899e9b4061737cbade4e1bb85f1b45c" +checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" dependencies = [ "dotenvy", "either", @@ -2686,9 +2758,9 @@ dependencies = [ [[package]] name = "sqlx-rt" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be52fc7c96c136cedea840ed54f7d446ff31ad670c9dea95ebcb998530971a3" +checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" dependencies = [ "native-tls", "once_cell", @@ -2720,9 +2792,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.99" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" dependencies = [ "proc-macro2", "quote", @@ -2752,26 +2824,52 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "tests" +version = "0.1.0" +dependencies = [ + "chrono", + "crossbeam-channel", + "ffplayout", + "ffplayout-lib", + "ffprobe", + "file-rotate", + "jsonrpc-http-server", + "lettre", + "log", + "notify", + "rand", + "regex", + "reqwest", + "serde", + "serde_json", + "serde_yaml", + "shlex", + "simplelog", + "time 0.3.15", + "walkdir", +] + [[package]] name = "textwrap" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -2791,9 +2889,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" +checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" dependencies = [ "itoa", "libc", @@ -2824,9 +2922,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.20.1" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg", "bytes", @@ -2834,7 +2932,6 @@ dependencies = [ "memchr", "mio 0.8.4", "num_cpus", - "once_cell", "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", @@ -2854,9 +2951,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", "pin-project-lite", @@ -2879,9 +2976,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -2899,9 +2996,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "log", @@ -2911,9 +3008,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] @@ -2963,24 +3060,30 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode_categories" @@ -2996,21 +3099,20 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna", - "matches", + "idna 0.3.0", "percent-encoding", ] [[package]] name = "uuid" -version = "1.1.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" +checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83" dependencies = [ "getrandom", ] @@ -3078,9 +3180,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3088,9 +3190,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -3103,9 +3205,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3115,9 +3217,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3125,9 +3227,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -3138,15 +3240,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -3278,7 +3380,7 @@ dependencies = [ [[package]] name = "zeromq" version = "0.3.3" -source = "git+https://github.com/zeromq/zmq.rs.git#6ca89efadd00d1cb3541c52094f4c92ce016ce11" +source = "git+https://github.com/zeromq/zmq.rs.git#7baeeffde9e4cb9741d1841cfdee5f00f354b578" dependencies = [ "async-std", "async-trait", @@ -3286,8 +3388,9 @@ dependencies = [ "bytes", "crossbeam-queue", "dashmap", - "enum-primitive-derive", - "futures", + "futures-channel", + "futures-io", + "futures-task", "futures-util", "log", "num-traits", diff --git a/Cargo.toml b/Cargo.toml index c325fc1d..6a8f57cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] -members = ["ffplayout-api", "ffplayout-engine", "lib"] -default-members = ["ffplayout-api", "ffplayout-engine"] +members = ["ffplayout-api", "ffplayout-engine", "lib", "tests"] +default-members = ["ffplayout-api", "ffplayout-engine", "tests"] [profile.release] opt-level = 3 diff --git a/README.md b/README.md index aaa6f23d..f5ddeab1 100644 --- a/README.md +++ b/README.md @@ -46,11 +46,15 @@ Check the [releases](https://github.com/ffplayout/ffplayout/releases/latest) for - JSON RPC server, for getting infos about current playing and controlling - [live ingest](/docs/live_ingest.md) - image source (will loop until out duration is reached) -- extra audio source (experimental) (has priority over audio from video source) +- extra audio source (experimental *) (has priority over audio from video source) +- [multiple audio tracks](/docs/multi_audio.md) (experimental *) - [custom filter](/docs/custom_filters.md) globally in config, or in playlist for specific clips +- import playlist from text or m3u file, with CLI or frontend For preview stream, read: [/docs/preview_stream.md](/docs/preview_stream.md) +**\* Experimental functions do not guarantee the same stability, also they can fail in unusual circumstances. The code and configuration options may change in the future.** + ## **ffplayout-api (ffpapi)** ffpapi serves the [frontend](https://github.com/ffplayout/ffplayout-frontend) and it acts as a [REST API](/ffplayout-api/README.md) for controlling the engine, manipulate playlists, add settings etc. diff --git a/assets/ffplayout.yml b/assets/ffplayout.yml index 573ea462..70e5ec0b 100644 --- a/assets/ffplayout.yml +++ b/assets/ffplayout.yml @@ -47,7 +47,8 @@ processing: or folder. 'aspect' must be a float number. 'logo' is only used if the path exist. 'logo_scale' scale the logo to target size, leave it blank when no scaling is needed, format is 'number:number', for example '100:-1' for proportional - scaling. With 'logo_opacity' logo can become transparent. With 'logo_filter' + scaling. With 'logo_opacity' logo can become transparent. With 'audio_tracks' it + is possible to configure how many audio tracks should be processed. With 'logo_filter' 'overlay=W-w-12:12' you can modify the logo position. With 'use_loudnorm' you can activate single pass EBU R128 loudness normalization. 'loud_*' can adjust the loudnorm filter. With 'custom_filter' it is possible, to apply further @@ -63,6 +64,7 @@ processing: logo_scale: logo_opacity: 0.7 logo_filter: overlay=W-w-12:12 + audio_tracks: 1 add_loudnorm: false loudnorm_ingest: false loud_i: -18 @@ -120,7 +122,7 @@ out: has the options 'desktop', 'hls', 'null', 'stream'. Use 'stream' and adjust 'output_param:' settings when you want to stream to a rtmp/rtsp/srt/... server. In production don't serve hls playlist with ffpapi, use nginx or another web server! - mode: desktop + mode: hls output_param: >- -c:v libx264 -crf 23 diff --git a/docs/README.md b/docs/README.md index d8eb1d01..6f62f1d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -21,6 +21,10 @@ Using live ingest to inject a live stream. The different output modes. +### **[Multi Audio Tracks](/docs/multi_audio.md)** + +Output multiple audio tracks. + ### **[Custom Filter](/docs/custom_filters.md)** Apply self defined audio/video filters. diff --git a/docs/api.md b/docs/api.md index d2b21627..1b65b917 100644 --- a/docs/api.md +++ b/docs/api.md @@ -324,3 +324,14 @@ curl -X POST http://127.0.0.1:8787/api/file/1/remove/ -H 'Content-Type: applicat curl -X POST http://127.0.0.1:8787/api/file/1/upload/ -H 'Authorization: ' -F "file=@file.mp4" ``` + +**Import playlist** + +Import text/m3u file and convert it to a playlist +lines with leading "#" will be ignore + +```BASH +curl -X POST http://127.0.0.1:8787/api/file/1/import/ -H 'Authorization: ' +-F "file=@list.m3u" +``` + diff --git a/docs/multi_audio.md b/docs/multi_audio.md new file mode 100644 index 00000000..c768e39f --- /dev/null +++ b/docs/multi_audio.md @@ -0,0 +1,73 @@ +## Multiple Audio Tracks + +**\* This is an experimental feature and more intended for advanced users. Use it with caution!** + +With _ffplayout_ you can output streams with multiple audio tracks, with some limitations: +* Not all formats support multiple audio tracks. For example _flv/rtmp_ doesn't support it. +* In your output parameters you need to set the correct mapping. + +ffmpeg filter usage and encoding parameters can become very complex, so it can happen that not every combination works out of the box. + +To get e better idea of what works, you can examine [engin_cmd](../tests/src/engine_cmd.rs). + +If you just output a single video stream with multiple audio tracks, let's say with `srt://` protocol, you only need to set in you config under `processing:` the correct `audio_tracks:` count. + +For multiple video resolutions and multiple audio tracks, the parameters could look like: + +```YAML +out: + ... + mode: stream + output_param: >- + -map 0:v + -map 0:a:0 + -map 0:a:1 + -c:v libx264 + -c:a aac + -ar 44100 + -b:a 128k + -flags +global_header + -f mpegts + srt://127.0.0.1:40051 + -map 0:v + -map 0:a:0 + -map 0:a:1 + -s 512x288 + -c:v libx264 + -c:a aac + -ar 44100 + -b:a 128k + -flags +global_header + -f mpegts + srt://127.0.0.1:40052 +``` + +If you need HLS output with multiple resolutions and audio tracks, you can try something like: + +```YAML +out: + ... + mode: hls + output_param: >- + -filter_complex [0:v]split=2[v1_out][v2];[v2]scale=w=512:h=288[v2_out];[0:a:0]asplit=2[a_0_1][a_0_2];[0:a:1]asplit=2[a_1_1][a_1_2] + -map [v1_out] + -map [a_0_1] + -map [a_1_1] + -c:v libx264 + -flags +cgop + -c:a aac + -map [v2_out] + -map [a_0_2] + -map [a_1_2] + -c:v:1 libx264 + -flags +cgop + -c:a:1 aac + -f hls + -hls_time 6 + -hls_list_size 600 + -hls_flags append_list+delete_segments+omit_endlist + -hls_segment_filename /usr/share/ffplayout/public/live/stream_%v-%d.ts + -master_pl_name master.m3u8 + -var_stream_map "v:0,a:0,a:1,name:720p v:1,a:2,a:3,name:288p" + /usr/share/ffplayout/public/live/stream_%v.m3u8 +``` diff --git a/docs/output.md b/docs/output.md index dacd2686..ba9874f8 100644 --- a/docs/output.md +++ b/docs/output.md @@ -126,7 +126,7 @@ HLS output is currently the default, mostly because it works out of the box and -f hls -hls_time 6 -hls_list_size 600 - -hls_flags append_list+delete_segments+omit_endlist+program_date_time + -hls_flags append_list+delete_segments+omit_endlist -hls_segment_filename /var/www/html/live/stream_%v-%d.ts -master_pl_name master.m3u8 -var_stream_map "v:0,a:0,name:720p v:1,a:1,name:540p v:2,a:2,name:360p" diff --git a/ffplayout-api/Cargo.toml b/ffplayout-api/Cargo.toml index 4b770827..5f44c3ab 100644 --- a/ffplayout-api/Cargo.toml +++ b/ffplayout-api/Cargo.toml @@ -4,7 +4,7 @@ description = "Rest API for ffplayout" license = "GPL-3.0" authors = ["Jonathan Baecker jonbae77@gmail.com"] readme = "README.md" -version = "0.6.2" +version = "0.7.0" edition = "2021" [dependencies] diff --git a/ffplayout-api/src/utils/auth.rs b/ffplayout-api/src/api/auth.rs similarity index 94% rename from ffplayout-api/src/utils/auth.rs rename to ffplayout-api/src/api/auth.rs index 009a2ec6..0ea64001 100644 --- a/ffplayout-api/src/utils/auth.rs +++ b/ffplayout-api/src/api/auth.rs @@ -11,14 +11,14 @@ const JWT_EXPIRATION_DAYS: i64 = 7; #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] pub struct Claims { - pub id: i64, + pub id: i32, pub username: String, pub role: String, exp: i64, } impl Claims { - pub fn new(id: i64, username: String, role: String) -> Self { + pub fn new(id: i32, username: String, role: String) -> Self { Self { id, username, diff --git a/ffplayout-api/src/api/mod.rs b/ffplayout-api/src/api/mod.rs new file mode 100644 index 00000000..474f258a --- /dev/null +++ b/ffplayout-api/src/api/mod.rs @@ -0,0 +1,2 @@ +pub mod auth; +pub mod routes; diff --git a/ffplayout-api/src/utils/routes.rs b/ffplayout-api/src/api/routes.rs similarity index 86% rename from ffplayout-api/src/utils/routes.rs rename to ffplayout-api/src/api/routes.rs index da750d4c..b0b6950d 100644 --- a/ffplayout-api/src/utils/routes.rs +++ b/ffplayout-api/src/api/routes.rs @@ -8,7 +8,7 @@ /// /// For all endpoints an (Bearer) authentication is required.\ /// `{id}` represent the channel id, and at default is 1. -use std::collections::HashMap; +use std::{collections::HashMap, env, fs, path::Path}; use actix_multipart::Multipart; use actix_web::{delete, get, http::StatusCode, patch, post, put, web, HttpResponse, Responder}; @@ -20,8 +20,12 @@ use argon2::{ use serde::{Deserialize, Serialize}; use simplelog::*; +use crate::auth::{create_jwt, Claims}; +use crate::db::{ + handles, + models::{Channel, LoginUser, TextPreset, User}, +}; use crate::utils::{ - auth::{create_jwt, Claims}, channels::{create_channel, delete_channel}, control::{control_service, control_state, media_info, send_message, Process}, errors::ServiceError, @@ -29,16 +33,10 @@ use crate::utils::{ browser, create_directory, remove_file_or_folder, rename_file, upload, MoveObject, PathObject, }, - handles::{ - db_add_preset, db_add_user, db_delete_preset, db_get_all_channels, db_get_channel, - db_get_presets, db_get_user, db_login, db_role, db_update_channel, db_update_preset, - db_update_user, - }, - models::{Channel, LoginUser, TextPreset, User}, playlist::{delete_playlist, generate_playlist, read_playlist, write_playlist}, - read_log_file, read_playout_config, Role, + playout_config, read_log_file, read_playout_config, Role, }; -use ffplayout_lib::utils::{JsonPlaylist, PlayoutConfig}; +use ffplayout_lib::utils::{import::import_file, JsonPlaylist, PlayoutConfig}; #[derive(Serialize)] struct ResponseObj { @@ -60,11 +58,19 @@ pub struct DateObj { } #[derive(Debug, Deserialize, Serialize)] -pub struct FileObj { +struct FileObj { #[serde(default)] path: String, } +#[derive(Debug, Deserialize, Serialize)] +pub struct ImportObj { + #[serde(default)] + file: String, + #[serde(default)] + date: String, +} + /// #### User Handling /// /// **Login** @@ -85,7 +91,7 @@ pub struct FileObj { /// ``` #[post("/auth/login/")] pub async fn login(credentials: web::Json) -> impl Responder { - match db_login(&credentials.username).await { + match handles::select_login(&credentials.username).await { Ok(mut user) => { let pass = user.password.clone(); let hash = PasswordHash::new(&pass).unwrap(); @@ -96,7 +102,7 @@ pub async fn login(credentials: web::Json) -> impl Responder { .verify_password(credentials.password.as_bytes(), &hash) .is_ok() { - let role = db_role(&user.role_id.unwrap_or_default()) + let role = handles::select_role(&user.role_id.unwrap_or_default()) .await .unwrap_or_else(|_| "guest".to_string()); let claims = Claims::new(user.id, user.username.clone(), role.clone()); @@ -147,7 +153,7 @@ pub async fn login(credentials: web::Json) -> impl Responder { #[get("/user")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] async fn get_user(user: web::ReqData) -> Result { - match db_get_user(&user.username).await { + match handles::select_user(&user.username).await { Ok(user) => Ok(web::Json(user)), Err(e) => { error!("{e}"); @@ -165,7 +171,7 @@ async fn get_user(user: web::ReqData) -> Result, + id: web::Path, user: web::ReqData, data: web::Json, ) -> Result { @@ -189,7 +195,7 @@ async fn update_user( fields.push_str(format!("password = '{}', salt = '{salt}'", password_hash).as_str()); } - if db_update_user(user.id, fields).await.is_ok() { + if handles::update_user(user.id, fields).await.is_ok() { return Ok("Update Success"); }; @@ -209,7 +215,7 @@ async fn update_user( #[post("/user/")] #[has_any_role("Role::Admin", type = "Role")] async fn add_user(data: web::Json) -> Result { - match db_add_user(data.into_inner()).await { + match handles::insert_user(data.into_inner()).await { Ok(_) => Ok("Add User Success"), Err(e) => { error!("{e}"); @@ -241,8 +247,8 @@ async fn add_user(data: web::Json) -> Result /// ``` #[get("/channel/{id}")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] -async fn get_channel(id: web::Path) -> Result { - if let Ok(channel) = db_get_channel(&id).await { +async fn get_channel(id: web::Path) -> Result { + if let Ok(channel) = handles::select_channel(&id).await { return Ok(web::Json(channel)); } @@ -257,7 +263,7 @@ async fn get_channel(id: web::Path) -> Result #[get("/channels")] #[has_any_role("Role::Admin", type = "Role")] async fn get_all_channels() -> Result { - if let Ok(channel) = db_get_all_channels().await { + if let Ok(channel) = handles::select_all_channels().await { return Ok(web::Json(channel)); } @@ -275,10 +281,13 @@ async fn get_all_channels() -> Result { #[patch("/channel/{id}")] #[has_any_role("Role::Admin", type = "Role")] async fn patch_channel( - id: web::Path, + id: web::Path, data: web::Json, ) -> Result { - if db_update_channel(*id, data.into_inner()).await.is_ok() { + if handles::update_channel(*id, data.into_inner()) + .await + .is_ok() + { return Ok("Update Success"); }; @@ -310,7 +319,7 @@ async fn add_channel(data: web::Json) -> Result) -> Result { +async fn remove_channel(id: web::Path) -> Result { if delete_channel(*id).await.is_ok() { return Ok("Delete Channel Success"); } @@ -330,10 +339,10 @@ async fn remove_channel(id: web::Path) -> Result, + id: web::Path, _details: AuthDetails, ) -> Result { - if let Ok(channel) = db_get_channel(&id).await { + if let Ok(channel) = handles::select_channel(&id).await { if let Ok(config) = read_playout_config(&channel.config_path) { return Ok(web::Json(config)); } @@ -351,10 +360,10 @@ async fn get_playout_config( #[put("/playout/config/{id}")] #[has_any_role("Role::Admin", type = "Role")] async fn update_playout_config( - id: web::Path, + id: web::Path, data: web::Json, ) -> Result { - if let Ok(channel) = db_get_channel(&id).await { + if let Ok(channel) = handles::select_channel(&id).await { if let Ok(f) = std::fs::OpenOptions::new() .write(true) .truncate(true) @@ -383,8 +392,8 @@ async fn update_playout_config( /// ``` #[get("/presets/{id}")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] -async fn get_presets(id: web::Path) -> Result { - if let Ok(presets) = db_get_presets(*id).await { +async fn get_presets(id: web::Path) -> Result { + if let Ok(presets) = handles::select_presets(*id).await { return Ok(web::Json(presets)); } @@ -402,10 +411,10 @@ async fn get_presets(id: web::Path) -> Result #[put("/presets/{id}")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] async fn update_preset( - id: web::Path, + id: web::Path, data: web::Json, ) -> Result { - if db_update_preset(&id, data.into_inner()).await.is_ok() { + if handles::update_preset(&id, data.into_inner()).await.is_ok() { return Ok("Update Success"); } @@ -423,7 +432,7 @@ async fn update_preset( #[post("/presets/")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] async fn add_preset(data: web::Json) -> Result { - if db_add_preset(data.into_inner()).await.is_ok() { + if handles::insert_preset(data.into_inner()).await.is_ok() { return Ok("Add preset Success"); } @@ -438,8 +447,8 @@ async fn add_preset(data: web::Json) -> Result) -> Result { - if db_delete_preset(&id).await.is_ok() { +async fn delete_preset(id: web::Path) -> Result { + if handles::delete_preset(&id).await.is_ok() { return Ok("Delete preset Success"); } @@ -466,7 +475,7 @@ async fn delete_preset(id: web::Path) -> Result, + id: web::Path, data: web::Json>, ) -> Result { match send_message(*id, data.into_inner()).await { @@ -488,7 +497,7 @@ pub async fn send_text_message( #[post("/control/{id}/playout/")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn control_playout( - id: web::Path, + id: web::Path, control: web::Json, ) -> Result { match control_state(*id, control.command.clone()).await { @@ -529,7 +538,7 @@ pub async fn control_playout( /// ``` #[get("/control/{id}/media/current")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] -pub async fn media_current(id: web::Path) -> Result { +pub async fn media_current(id: web::Path) -> Result { match media_info(*id, "current".into()).await { Ok(res) => Ok(res.text().await.unwrap_or_else(|_| "Success".into())), Err(e) => Err(e), @@ -543,7 +552,7 @@ pub async fn media_current(id: web::Path) -> Result) -> Result { +pub async fn media_next(id: web::Path) -> Result { match media_info(*id, "next".into()).await { Ok(res) => Ok(res.text().await.unwrap_or_else(|_| "Success".into())), Err(e) => Err(e), @@ -558,7 +567,7 @@ pub async fn media_next(id: web::Path) -> Result) -> Result { +pub async fn media_last(id: web::Path) -> Result { match media_info(*id, "last".into()).await { Ok(res) => Ok(res.text().await.unwrap_or_else(|_| "Success".into())), Err(e) => Err(e), @@ -581,7 +590,7 @@ pub async fn media_last(id: web::Path) -> Result, + id: web::Path, proc: web::Json, ) -> Result { control_service(*id, &proc.command).await @@ -598,7 +607,7 @@ pub async fn process_control( #[get("/playlist/{id}")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn get_playlist( - id: web::Path, + id: web::Path, obj: web::Query, ) -> Result { match read_playlist(*id, obj.date.clone()).await { @@ -617,7 +626,7 @@ pub async fn get_playlist( #[post("/playlist/{id}/")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn save_playlist( - id: web::Path, + id: web::Path, data: web::Json, ) -> Result { match write_playlist(*id, data.into_inner()).await { @@ -637,7 +646,7 @@ pub async fn save_playlist( #[get("/playlist/{id}/generate/{date}")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn gen_playlist( - params: web::Path<(i64, String)>, + params: web::Path<(i32, String)>, ) -> Result { match generate_playlist(params.0, params.1.clone()).await { Ok(playlist) => Ok(web::Json(playlist)), @@ -654,7 +663,7 @@ pub async fn gen_playlist( #[delete("/playlist/{id}/{date}")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn del_playlist( - params: web::Path<(i64, String)>, + params: web::Path<(i32, String)>, ) -> Result { match delete_playlist(params.0, ¶ms.1).await { Ok(_) => Ok(format!("Delete playlist from {} success!", params.1)), @@ -673,7 +682,7 @@ pub async fn del_playlist( #[get("/log/{id}")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn get_log( - id: web::Path, + id: web::Path, log: web::Query, ) -> Result { read_log_file(&id, &log.date).await @@ -690,7 +699,7 @@ pub async fn get_log( #[post("/file/{id}/browse/")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn file_browser( - id: web::Path, + id: web::Path, data: web::Json, ) -> Result { match browser(*id, &data.into_inner()).await { @@ -708,7 +717,7 @@ pub async fn file_browser( #[post("/file/{id}/create-folder/")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn add_dir( - id: web::Path, + id: web::Path, data: web::Json, ) -> Result { create_directory(*id, &data.into_inner()).await @@ -723,7 +732,7 @@ pub async fn add_dir( #[post("/file/{id}/rename/")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn move_rename( - id: web::Path, + id: web::Path, data: web::Json, ) -> Result { match rename_file(*id, &data.into_inner()).await { @@ -741,7 +750,7 @@ pub async fn move_rename( #[post("/file/{id}/remove/")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] pub async fn remove( - id: web::Path, + id: web::Path, data: web::Json, ) -> Result { match remove_file_or_folder(*id, &data.into_inner().source).await { @@ -759,9 +768,38 @@ pub async fn remove( #[put("/file/{id}/upload/")] #[has_any_role("Role::Admin", "Role::User", type = "Role")] async fn save_file( - id: web::Path, + id: web::Path, payload: Multipart, obj: web::Query, ) -> Result { - upload(*id, payload, &obj.path).await + upload(*id, payload, &obj.path, false).await +} + +/// **Import playlist** +/// +/// Import text/m3u file and convert it to a playlist +/// lines with leading "#" will be ignore +/// +/// ```BASH +/// curl -X POST http://127.0.0.1:8787/api/file/1/import/ -H 'Authorization: ' +/// -F "file=@list.m3u" +/// ``` +#[put("/file/{id}/import/")] +#[has_any_role("Role::Admin", "Role::User", type = "Role")] +async fn import_playlist( + id: web::Path, + payload: Multipart, + obj: web::Query, +) -> Result { + let file = Path::new(&obj.file).file_name().unwrap_or_default(); + let path = env::temp_dir().join(&file).to_string_lossy().to_string(); + let (config, _) = playout_config(&id).await?; + let channel = handles::select_channel(&id).await?; + + upload(*id, payload, &path, true).await?; + import_file(&config, &obj.date, Some(channel.name), &path)?; + + fs::remove_file(path)?; + + Ok(HttpResponse::Ok().into()) } diff --git a/ffplayout-api/src/utils/handles.rs b/ffplayout-api/src/db/handles.rs similarity index 84% rename from ffplayout-api/src/utils/handles.rs rename to ffplayout-api/src/db/handles.rs index f505b5de..c106a3a5 100644 --- a/ffplayout-api/src/utils/handles.rs +++ b/ffplayout-api/src/db/handles.rs @@ -7,11 +7,8 @@ use rand::{distributions::Alphanumeric, Rng}; use simplelog::*; use sqlx::{migrate::MigrateDatabase, sqlite::SqliteQueryResult, Pool, Sqlite, SqlitePool}; -use crate::utils::{ - db_path, local_utc_offset, - models::{Channel, TextPreset, User}, - GlobalSettings, -}; +use crate::db::models::{Channel, TextPreset, User}; +use crate::utils::{db_path, local_utc_offset, GlobalSettings}; #[derive(Debug, sqlx::FromRow)] struct Role { @@ -19,7 +16,7 @@ struct Role { } async fn create_schema() -> Result { - let conn = db_connection().await?; + let conn = connection().await?; let query = "PRAGMA foreign_keys = ON; CREATE TABLE IF NOT EXISTS global ( @@ -96,7 +93,7 @@ pub async fn db_init(domain: Option) -> Result<&'static str, Box format!("http://{d}/live/stream.m3u8"), @@ -130,15 +127,15 @@ pub async fn db_init(domain: Option) -> Result<&'static str, Box Result, sqlx::Error> { +pub async fn connection() -> Result, sqlx::Error> { let db_path = db_path().unwrap(); let conn = SqlitePool::connect(&db_path).await?; Ok(conn) } -pub async fn db_global() -> Result { - let conn = db_connection().await?; +pub async fn select_global() -> Result { + let conn = connection().await?; let query = "SELECT secret FROM global WHERE id = 1"; let result: GlobalSettings = sqlx::query_as(query).fetch_one(&conn).await?; conn.close().await; @@ -146,8 +143,8 @@ pub async fn db_global() -> Result { Ok(result) } -pub async fn db_get_channel(id: &i64) -> Result { - let conn = db_connection().await?; +pub async fn select_channel(id: &i32) -> Result { + let conn = connection().await?; let query = "SELECT * FROM channels WHERE id = $1"; let mut result: Channel = sqlx::query_as(query).bind(id).fetch_one(&conn).await?; conn.close().await; @@ -157,8 +154,8 @@ pub async fn db_get_channel(id: &i64) -> Result { Ok(result) } -pub async fn db_get_all_channels() -> Result, sqlx::Error> { - let conn = db_connection().await?; +pub async fn select_all_channels() -> Result, sqlx::Error> { + let conn = connection().await?; let query = "SELECT * FROM channels"; let mut results: Vec = sqlx::query_as(query).fetch_all(&conn).await?; conn.close().await; @@ -170,11 +167,8 @@ pub async fn db_get_all_channels() -> Result, sqlx::Error> { Ok(results) } -pub async fn db_update_channel( - id: i64, - channel: Channel, -) -> Result { - let conn = db_connection().await?; +pub async fn update_channel(id: i32, channel: Channel) -> Result { + let conn = connection().await?; let query = "UPDATE channels SET name = $2, preview_url = $3, config_path = $4, extra_extensions = $5 WHERE id = $1"; let result: SqliteQueryResult = sqlx::query(query) @@ -190,8 +184,8 @@ pub async fn db_update_channel( Ok(result) } -pub async fn db_add_channel(channel: Channel) -> Result { - let conn = db_connection().await?; +pub async fn insert_channel(channel: Channel) -> Result { + let conn = connection().await?; let query = "INSERT INTO channels (name, preview_url, config_path, extra_extensions, service) VALUES($1, $2, $3, $4, $5)"; let result = sqlx::query(query) @@ -211,8 +205,8 @@ pub async fn db_add_channel(channel: Channel) -> Result { Ok(new_channel) } -pub async fn db_delete_channel(id: &i64) -> Result { - let conn = db_connection().await?; +pub async fn delete_channel(id: &i32) -> Result { + let conn = connection().await?; let query = "DELETE FROM channels WHERE id = $1"; let result: SqliteQueryResult = sqlx::query(query).bind(id).execute(&conn).await?; @@ -221,8 +215,8 @@ pub async fn db_delete_channel(id: &i64) -> Result Result { - let conn = db_connection().await?; +pub async fn select_role(id: &i32) -> Result { + let conn = connection().await?; let query = "SELECT name FROM roles WHERE id = $1"; let result: Role = sqlx::query_as(query).bind(id).fetch_one(&conn).await?; conn.close().await; @@ -230,8 +224,8 @@ pub async fn db_role(id: &i64) -> Result { Ok(result.name) } -pub async fn db_login(user: &str) -> Result { - let conn = db_connection().await?; +pub async fn select_login(user: &str) -> Result { + let conn = connection().await?; let query = "SELECT id, mail, username, password, salt, role_id FROM user WHERE username = $1"; let result: User = sqlx::query_as(query).bind(user).fetch_one(&conn).await?; conn.close().await; @@ -239,8 +233,8 @@ pub async fn db_login(user: &str) -> Result { Ok(result) } -pub async fn db_get_user(user: &str) -> Result { - let conn = db_connection().await?; +pub async fn select_user(user: &str) -> Result { + let conn = connection().await?; let query = "SELECT id, mail, username, role_id FROM user WHERE username = $1"; let result: User = sqlx::query_as(query).bind(user).fetch_one(&conn).await?; conn.close().await; @@ -248,8 +242,8 @@ pub async fn db_get_user(user: &str) -> Result { Ok(result) } -pub async fn db_add_user(user: User) -> Result { - let conn = db_connection().await?; +pub async fn insert_user(user: User) -> Result { + let conn = connection().await?; let salt = SaltString::generate(&mut OsRng); let password_hash = Argon2::default() .hash_password(user.password.clone().as_bytes(), &salt) @@ -270,8 +264,8 @@ pub async fn db_add_user(user: User) -> Result { Ok(result) } -pub async fn db_update_user(id: i64, fields: String) -> Result { - let conn = db_connection().await?; +pub async fn update_user(id: i32, fields: String) -> Result { + let conn = connection().await?; let query = format!("UPDATE user SET {fields} WHERE id = $1"); let result: SqliteQueryResult = sqlx::query(&query).bind(id).execute(&conn).await?; conn.close().await; @@ -279,8 +273,8 @@ pub async fn db_update_user(id: i64, fields: String) -> Result Result, sqlx::Error> { - let conn = db_connection().await?; +pub async fn select_presets(id: i32) -> Result, sqlx::Error> { + let conn = connection().await?; let query = "SELECT * FROM presets WHERE channel_id = $1"; let result: Vec = sqlx::query_as(query).bind(id).fetch_all(&conn).await?; conn.close().await; @@ -288,11 +282,8 @@ pub async fn db_get_presets(id: i64) -> Result, sqlx::Error> { Ok(result) } -pub async fn db_update_preset( - id: &i64, - preset: TextPreset, -) -> Result { - let conn = db_connection().await?; +pub async fn update_preset(id: &i32, preset: TextPreset) -> Result { + let conn = connection().await?; let query = "UPDATE presets SET name = $1, text = $2, x = $3, y = $4, fontsize = $5, line_spacing = $6, fontcolor = $7, alpha = $8, box = $9, boxcolor = $10, boxborderw = 11 WHERE id = $12"; @@ -316,8 +307,8 @@ pub async fn db_update_preset( Ok(result) } -pub async fn db_add_preset(preset: TextPreset) -> Result { - let conn = db_connection().await?; +pub async fn insert_preset(preset: TextPreset) -> Result { + let conn = connection().await?; let query = "INSERT INTO presets (channel_id, name, text, x, y, fontsize, line_spacing, fontcolor, alpha, box, boxcolor, boxborderw) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)"; @@ -341,8 +332,8 @@ pub async fn db_add_preset(preset: TextPreset) -> Result Result { - let conn = db_connection().await?; +pub async fn delete_preset(id: &i32) -> Result { + let conn = connection().await?; let query = "DELETE FROM presets WHERE id = $1;"; let result: SqliteQueryResult = sqlx::query(query).bind(id).execute(&conn).await?; conn.close().await; diff --git a/ffplayout-api/src/db/mod.rs b/ffplayout-api/src/db/mod.rs new file mode 100644 index 00000000..bec83121 --- /dev/null +++ b/ffplayout-api/src/db/mod.rs @@ -0,0 +1,2 @@ +pub mod handles; +pub mod models; diff --git a/ffplayout-api/src/utils/models.rs b/ffplayout-api/src/db/models.rs similarity index 87% rename from ffplayout-api/src/utils/models.rs rename to ffplayout-api/src/db/models.rs index df57b73e..bc7e5247 100644 --- a/ffplayout-api/src/utils/models.rs +++ b/ffplayout-api/src/db/models.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; pub struct User { #[sqlx(default)] #[serde(skip_deserializing)] - pub id: i64, + pub id: i32, #[sqlx(default)] pub mail: Option, pub username: String, @@ -16,10 +16,10 @@ pub struct User { pub salt: Option, #[sqlx(default)] #[serde(skip_serializing)] - pub role_id: Option, + pub role_id: Option, #[sqlx(default)] #[serde(skip_serializing)] - pub channel_id: Option, + pub channel_id: Option, #[sqlx(default)] pub token: Option, } @@ -30,12 +30,12 @@ fn empty_string() -> String { #[derive(Debug, Deserialize, Serialize, Clone)] pub struct LoginUser { - pub id: i64, + pub id: i32, pub username: String, } impl LoginUser { - pub fn new(id: i64, username: String) -> Self { + pub fn new(id: i32, username: String) -> Self { Self { id, username } } } @@ -43,8 +43,8 @@ impl LoginUser { pub struct TextPreset { #[sqlx(default)] #[serde(skip_deserializing)] - pub id: i64, - pub channel_id: i64, + pub id: i32, + pub channel_id: i32, pub name: String, pub text: String, pub x: String, @@ -61,7 +61,7 @@ pub struct TextPreset { #[derive(Debug, Deserialize, Serialize, sqlx::FromRow)] pub struct Channel { #[serde(skip_deserializing)] - pub id: i64, + pub id: i32, pub name: String, pub preview_url: String, pub config_path: String, diff --git a/ffplayout-api/src/main.rs b/ffplayout-api/src/main.rs index 2b651475..349d1394 100644 --- a/ffplayout-api/src/main.rs +++ b/ffplayout-api/src/main.rs @@ -9,21 +9,23 @@ use actix_web_httpauth::middleware::HttpAuthentication; use clap::Parser; use simplelog::*; +pub mod api; +pub mod db; pub mod utils; -use utils::{ - args_parse::Args, - auth, db_path, init_config, - models::LoginUser, +use api::{ + auth, routes::{ add_channel, add_dir, add_preset, add_user, control_playout, del_playlist, delete_preset, file_browser, gen_playlist, get_all_channels, get_channel, get_log, get_playlist, - get_playout_config, get_presets, get_user, login, media_current, media_last, media_next, - move_rename, patch_channel, process_control, remove, remove_channel, save_file, - save_playlist, send_text_message, update_playout_config, update_preset, update_user, + get_playout_config, get_presets, get_user, import_playlist, login, media_current, + media_last, media_next, move_rename, patch_channel, process_control, remove, + remove_channel, save_file, save_playlist, send_text_message, update_playout_config, + update_preset, update_user, }, - run_args, Role, }; +use db::models::LoginUser; +use utils::{args_parse::Args, db_path, init_config, run_args, Role}; use ffplayout_lib::utils::{init_logging, PlayoutConfig}; @@ -118,7 +120,8 @@ async fn main() -> std::io::Result<()> { .service(add_dir) .service(move_rename) .service(remove) - .service(save_file), + .service(save_file) + .service(import_playlist), ) .service(Files::new("/", public_path()).index_file("index.html")) }) diff --git a/ffplayout-api/src/utils/channels.rs b/ffplayout-api/src/utils/channels.rs index 9c6c145b..191a5018 100644 --- a/ffplayout-api/src/utils/channels.rs +++ b/ffplayout-api/src/utils/channels.rs @@ -2,12 +2,9 @@ use std::fs; use simplelog::*; -use crate::utils::{ - control::control_service, - errors::ServiceError, - handles::{db_add_channel, db_delete_channel, db_get_channel}, - models::Channel, -}; +use crate::utils::{control::control_service, errors::ServiceError}; + +use crate::db::{handles, models::Channel}; pub async fn create_channel(target_channel: Channel) -> Result { if !target_channel.service.starts_with("ffplayout@") { @@ -23,14 +20,14 @@ pub async fn create_channel(target_channel: Channel) -> Result Result<(), ServiceError> { - let channel = db_get_channel(&id).await?; +pub async fn delete_channel(id: i32) -> Result<(), ServiceError> { + let channel = handles::select_channel(&id).await?; control_service(channel.id, "stop").await?; control_service(channel.id, "disable").await?; @@ -38,7 +35,7 @@ pub async fn delete_channel(id: i64) -> Result<(), ServiceError> { error!("{e}"); }; - db_delete_channel(&id).await?; + handles::delete_channel(&id).await?; Ok(()) } diff --git a/ffplayout-api/src/utils/control.rs b/ffplayout-api/src/utils/control.rs index 692d43aa..0b5eb068 100644 --- a/ffplayout-api/src/utils/control.rs +++ b/ffplayout-api/src/utils/control.rs @@ -6,13 +6,14 @@ use reqwest::{ }; use serde::{Deserialize, Serialize}; -use crate::utils::{errors::ServiceError, handles::db_get_channel, playout_config}; +use crate::db::handles::select_channel; +use crate::utils::{errors::ServiceError, playout_config}; use ffplayout_lib::vec_strings; #[derive(Debug, Deserialize, Serialize, Clone)] struct RpcObj { jsonrpc: String, - id: i64, + id: i32, method: String, params: T, } @@ -34,7 +35,7 @@ struct MediaParams { } impl RpcObj { - fn new(id: i64, method: String, params: T) -> Self { + fn new(id: i32, method: String, params: T) -> Self { Self { jsonrpc: "2.0".into(), id, @@ -55,8 +56,8 @@ struct SystemD { } impl SystemD { - async fn new(id: i64) -> Result { - let channel = db_get_channel(&id).await?; + async fn new(id: i32) -> Result { + let channel = select_channel(&id).await?; Ok(Self { service: channel.service, @@ -129,7 +130,7 @@ fn create_header(auth: &str) -> HeaderMap { headers } -async fn post_request(id: i64, obj: RpcObj) -> Result +async fn post_request(id: i32, obj: RpcObj) -> Result where T: Serialize, { @@ -150,7 +151,7 @@ where } pub async fn send_message( - id: i64, + id: i32, message: HashMap, ) -> Result { let json_obj = RpcObj::new( @@ -165,19 +166,19 @@ pub async fn send_message( post_request(id, json_obj).await } -pub async fn control_state(id: i64, command: String) -> Result { +pub async fn control_state(id: i32, command: String) -> Result { let json_obj = RpcObj::new(id, "player".into(), ControlParams { control: command }); post_request(id, json_obj).await } -pub async fn media_info(id: i64, command: String) -> Result { +pub async fn media_info(id: i32, command: String) -> Result { let json_obj = RpcObj::new(id, "player".into(), MediaParams { media: command }); post_request(id, json_obj).await } -pub async fn control_service(id: i64, command: &str) -> Result { +pub async fn control_service(id: i32, command: &str) -> Result { let system_d = SystemD::new(id).await?; match command { diff --git a/ffplayout-api/src/utils/files.rs b/ffplayout-api/src/utils/files.rs index 3672990f..e5db7027 100644 --- a/ffplayout-api/src/utils/files.rs +++ b/ffplayout-api/src/utils/files.rs @@ -47,9 +47,9 @@ pub struct VideoFile { /// /// This function takes care, that it is not possible to break out from root_path. /// It also gives alway a relative path back. -fn norm_abs_path(root_path: &String, input_path: &String) -> (PathBuf, String, String) { - let mut path = PathBuf::from(root_path.clone()); - let path_relative = RelativePath::new(&root_path) +fn norm_abs_path(root_path: &str, input_path: &str) -> (PathBuf, String, String) { + let mut path = PathBuf::from(root_path); + let path_relative = RelativePath::new(root_path) .normalize() .to_string() .replace("../", ""); @@ -57,7 +57,11 @@ fn norm_abs_path(root_path: &String, input_path: &String) -> (PathBuf, String, S .normalize() .to_string() .replace("../", ""); - let path_suffix = path.file_name().unwrap().to_string_lossy().to_string(); + let path_suffix = path + .file_name() + .unwrap_or_default() + .to_string_lossy() + .to_string(); if input_path.starts_with(root_path) || source_relative.starts_with(&path_relative) { source_relative = source_relative @@ -83,7 +87,7 @@ fn norm_abs_path(root_path: &String, input_path: &String) -> (PathBuf, String, S /// Take input path and give file and folder list from it back. /// Input should be a relative path segment, but when it is a absolut path, the norm_abs_path function /// will take care, that user can not break out from given storage path in config. -pub async fn browser(id: i64, path_obj: &PathObject) -> Result { +pub async fn browser(id: i32, path_obj: &PathObject) -> Result { let (config, _) = playout_config(&id).await?; let extensions = config.storage.extensions; let (path, parent, path_component) = norm_abs_path(&config.storage.path, &path_obj.source); @@ -139,7 +143,7 @@ pub async fn browser(id: i64, path_obj: &PathObject) -> Result Result { let (config, _) = playout_config(&id).await?; @@ -194,7 +198,7 @@ fn rename(source: &PathBuf, target: &PathBuf) -> Result Result { +pub async fn rename_file(id: i32, move_object: &MoveObject) -> Result { let (config, _) = playout_config(&id).await?; let (source_path, _, _) = norm_abs_path(&config.storage.path, &move_object.source); let (mut target_path, _, _) = norm_abs_path(&config.storage.path, &move_object.target); @@ -225,7 +229,7 @@ pub async fn rename_file(id: i64, move_object: &MoveObject) -> Result Result<(), ServiceError> { +pub async fn remove_file_or_folder(id: i32, source_path: &str) -> Result<(), ServiceError> { let (config, _) = playout_config(&id).await?; let (source, _, _) = norm_abs_path(&config.storage.path, source_path); @@ -258,7 +262,7 @@ pub async fn remove_file_or_folder(id: i64, source_path: &String) -> Result<(), Err(ServiceError::InternalServerError) } -async fn valid_path(id: i64, path: &String) -> Result { +async fn valid_path(id: i32, path: &str) -> Result { let (config, _) = playout_config(&id).await?; let (test_path, _, _) = norm_abs_path(&config.storage.path, path); @@ -270,9 +274,10 @@ async fn valid_path(id: i64, path: &String) -> Result { } pub async fn upload( - id: i64, + id: i32, mut payload: Multipart, - path: &String, + path: &str, + abs_path: bool, ) -> Result { while let Some(mut field) = payload.try_next().await? { let content_disposition = field.content_disposition(); @@ -286,8 +291,14 @@ pub async fn upload( .get_filename() .map_or_else(|| rand_string.to_string(), sanitize_filename::sanitize); - let target_path = valid_path(id, path).await?; - let filepath = target_path.join(filename); + let filepath; + + if abs_path { + filepath = PathBuf::from(path); + } else { + let target_path = valid_path(id, path).await?; + filepath = target_path.join(filename); + } if filepath.is_file() { return Err(ServiceError::BadRequest("Target already exists!".into())); diff --git a/ffplayout-api/src/utils/mod.rs b/ffplayout-api/src/utils/mod.rs index e60ed063..df98c697 100644 --- a/ffplayout-api/src/utils/mod.rs +++ b/ffplayout-api/src/utils/mod.rs @@ -12,22 +12,17 @@ use rpassword::read_password; use simplelog::*; pub mod args_parse; -pub mod auth; pub mod channels; pub mod control; pub mod errors; pub mod files; -pub mod handles; -pub mod models; pub mod playlist; -pub mod routes; -use crate::utils::{ - args_parse::Args, - errors::ServiceError, - handles::{db_add_user, db_get_channel, db_global, db_init}, +use crate::db::{ + handles::{db_init, insert_user, select_channel, select_global}, models::{Channel, User}, }; +use crate::utils::{args_parse::Args, errors::ServiceError}; use ffplayout_lib::utils::PlayoutConfig; #[derive(Clone, Eq, PartialEq)] @@ -54,7 +49,7 @@ pub struct GlobalSettings { impl GlobalSettings { async fn new() -> Self { - let global_settings = db_global(); + let global_settings = select_global(); match global_settings.await { Ok(g) => g, @@ -165,7 +160,7 @@ pub async fn run_args(mut args: Args) -> Result<(), i32> { token: None, }; - if let Err(e) = db_add_user(user).await { + if let Err(e) = insert_user(user).await { error!("{e}"); return Err(1); }; @@ -185,8 +180,8 @@ pub fn read_playout_config(path: &str) -> Result> Ok(config) } -pub async fn playout_config(channel_id: &i64) -> Result<(PlayoutConfig, Channel), ServiceError> { - if let Ok(channel) = db_get_channel(channel_id).await { +pub async fn playout_config(channel_id: &i32) -> Result<(PlayoutConfig, Channel), ServiceError> { + if let Ok(channel) = select_channel(channel_id).await { if let Ok(config) = read_playout_config(&channel.config_path.clone()) { return Ok((config, channel)); } @@ -197,8 +192,8 @@ pub async fn playout_config(channel_id: &i64) -> Result<(PlayoutConfig, Channel) )) } -pub async fn read_log_file(channel_id: &i64, date: &str) -> Result { - if let Ok(channel) = db_get_channel(channel_id).await { +pub async fn read_log_file(channel_id: &i32, date: &str) -> Result { + if let Ok(channel) = select_channel(channel_id).await { let mut date_str = "".to_string(); if !date.is_empty() { diff --git a/ffplayout-api/src/utils/playlist.rs b/ffplayout-api/src/utils/playlist.rs index 33c38d7b..3821fb04 100644 --- a/ffplayout-api/src/utils/playlist.rs +++ b/ffplayout-api/src/utils/playlist.rs @@ -1,33 +1,13 @@ -use std::{ - fs::{self, File}, - io::Error, - path::PathBuf, -}; +use std::{fs, path::PathBuf}; use simplelog::*; use crate::utils::{errors::ServiceError, playout_config}; -use ffplayout_lib::utils::{generate_playlist as playlist_generator, JsonPlaylist}; +use ffplayout_lib::utils::{ + generate_playlist as playlist_generator, json_reader, json_writer, JsonPlaylist, +}; -fn json_reader(path: &PathBuf) -> Result { - let f = File::options().read(true).write(false).open(&path)?; - let p = serde_json::from_reader(f)?; - - Ok(p) -} - -fn json_writer(path: &PathBuf, data: JsonPlaylist) -> Result<(), Error> { - let f = File::options() - .write(true) - .truncate(true) - .create(true) - .open(&path)?; - serde_json::to_writer_pretty(f, &data)?; - - Ok(()) -} - -pub async fn read_playlist(id: i64, date: String) -> Result { +pub async fn read_playlist(id: i32, date: String) -> Result { let (config, _) = playout_config(&id).await?; let mut playlist_path = PathBuf::from(&config.playlist.path); let d: Vec<&str> = date.split('-').collect(); @@ -43,7 +23,7 @@ pub async fn read_playlist(id: i64, date: String) -> Result Result { +pub async fn write_playlist(id: i32, json_data: JsonPlaylist) -> Result { let (config, _) = playout_config(&id).await?; let date = json_data.date.clone(); let mut playlist_path = PathBuf::from(&config.playlist.path); @@ -88,7 +68,7 @@ pub async fn write_playlist(id: i64, json_data: JsonPlaylist) -> Result Result { +pub async fn generate_playlist(id: i32, date: String) -> Result { let (mut config, channel) = playout_config(&id).await?; config.general.generate = Some(vec![date.clone()]); @@ -109,7 +89,7 @@ pub async fn generate_playlist(id: i64, date: String) -> Result Result<(), ServiceError> { +pub async fn delete_playlist(id: i32, date: &str) -> Result<(), ServiceError> { let (config, _) = playout_config(&id).await?; let mut playlist_path = PathBuf::from(&config.playlist.path); let d: Vec<&str> = date.split('-').collect(); diff --git a/ffplayout-engine/Cargo.toml b/ffplayout-engine/Cargo.toml index baa45227..3533c9de 100644 --- a/ffplayout-engine/Cargo.toml +++ b/ffplayout-engine/Cargo.toml @@ -4,8 +4,9 @@ description = "24/7 playout based on rust and ffmpeg" license = "GPL-3.0" authors = ["Jonathan Baecker jonbae77@gmail.com"] readme = "README.md" -version = "0.15.2" +version = "0.16.0" edition = "2021" +default-run = "ffplayout" [dependencies] ffplayout-lib = { path = "../lib" } @@ -15,6 +16,7 @@ crossbeam-channel = "0.5" futures = "0.3" jsonrpc-http-server = "18.0" notify = "4.0" +regex = "1" reqwest = { version = "0.11", features = ["blocking", "json"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/ffplayout-engine/README.md b/ffplayout-engine/README.md index a2aea8d9..f8bce14a 100644 --- a/ffplayout-engine/README.md +++ b/ffplayout-engine/README.md @@ -8,11 +8,14 @@ ffplayout also allows the passing of parameters: ``` OPTIONS: - -c, --config File path to ffplayout.conf + -c, --config File path to ffplayout.yml + -d, --date Target date (YYYY-MM-DD) for text/m3u to playlist import -f, --folder Play folder content - -g, --generate ... Generate playlist for date or date-range, like: 2022-01-01 - 2022-01-10: + --fake-time fake date time, for debugging + -g, --generate ... Generate playlist for dates, like: 2022-01-01 - 2022-01-10 -h, --help Print help information -i, --infinit Loop playlist infinitely + --import Import a given text/m3u file and create a playlist from it -l, --log File path for logging -m, --play-mode Playing mode: folder, playlist -o, --output Set output mode: desktop, hls, stream diff --git a/ffplayout-engine/src/input/folder.rs b/ffplayout-engine/src/input/folder.rs index 343bb787..d3f57a19 100644 --- a/ffplayout-engine/src/input/folder.rs +++ b/ffplayout-engine/src/input/folder.rs @@ -42,7 +42,7 @@ pub fn watchman( match res { Create(new_path) => { let index = sources.lock().unwrap().len(); - let media = Media::new(index, new_path.display().to_string(), false); + let media = Media::new(index, &new_path.to_string_lossy(), false); if include_file(config.clone(), &new_path) { sources.lock().unwrap().push(media); @@ -66,7 +66,7 @@ pub fn watchman( .position(|x| *x.source == old_path.display().to_string()) .unwrap(); - let media = Media::new(index, new_path.display().to_string(), false); + let media = Media::new(index, &new_path.to_string_lossy(), false); sources.lock().unwrap()[index] = media; info!("Rename file: {old_path:?} to {new_path:?}"); diff --git a/ffplayout-engine/src/input/ingest.rs b/ffplayout-engine/src/input/ingest.rs index ac1ca98b..5674b941 100644 --- a/ffplayout-engine/src/input/ingest.rs +++ b/ffplayout-engine/src/input/ingest.rs @@ -84,7 +84,7 @@ pub fn ingest_server( let mut buffer: [u8; 65088] = [0; 65088]; let mut server_cmd = vec_strings!["-hide_banner", "-nostats", "-v", "level+info"]; let stream_input = config.ingest.input_cmd.clone().unwrap(); - let mut dummy_media = Media::new(0, "Live Stream".to_string(), false); + let mut dummy_media = Media::new(0, "Live Stream", false); dummy_media.is_live = Some(true); let mut filters = filter_chains(&config, &mut dummy_media, &Arc::new(Mutex::new(vec![]))); diff --git a/ffplayout-engine/src/input/mod.rs b/ffplayout-engine/src/input/mod.rs index 15e4a8dc..cca35600 100644 --- a/ffplayout-engine/src/input/mod.rs +++ b/ffplayout-engine/src/input/mod.rs @@ -1,5 +1,4 @@ use std::{ - process, sync::{ atomic::{AtomicBool, AtomicUsize}, Arc, Mutex, @@ -9,7 +8,7 @@ use std::{ use simplelog::*; -use ffplayout_lib::utils::{Media, PlayoutConfig, PlayoutStatus}; +use ffplayout_lib::utils::{Media, PlayoutConfig, PlayoutStatus, ProcessMode::*}; pub mod folder; pub mod ingest; @@ -29,8 +28,8 @@ pub fn source_generator( playout_stat: PlayoutStatus, is_terminated: Arc, ) -> Box> { - let get_source = match config.processing.mode.as_str() { - "folder" => { + match config.processing.mode { + Folder => { info!("Playout in folder mode"); debug!( "Monitor folder: {}", @@ -46,18 +45,12 @@ pub fn source_generator( Box::new(folder_source) as Box> } - "playlist" => { + Playlist => { info!("Playout in playlist mode"); let program = CurrentProgram::new(&config, playout_stat, is_terminated, current_list, index); Box::new(program) as Box> } - _ => { - error!("Process Mode not exists!"); - process::exit(1); - } - }; - - get_source + } } diff --git a/ffplayout-engine/src/input/playlist.rs b/ffplayout-engine/src/input/playlist.rs index 8da5122e..cdd5cd8a 100644 --- a/ffplayout-engine/src/input/playlist.rs +++ b/ffplayout-engine/src/input/playlist.rs @@ -69,7 +69,7 @@ impl CurrentProgram { json_path: json.current_file, json_date: json.date, nodes: current_list, - current_node: Media::new(0, String::new(), false), + current_node: Media::new(0, "", false), index: global_index, is_terminated, playout_stat, @@ -118,7 +118,7 @@ impl CurrentProgram { "Playlist {} not exists!", self.json_path.clone().unwrap() ); - let mut media = Media::new(0, String::new(), false); + let mut media = Media::new(0, "", false); media.begin = Some(get_sec()); media.duration = DUMMY_LEN; media.out = DUMMY_LEN; @@ -304,7 +304,7 @@ impl Iterator for CurrentProgram { current_time += self.config.playlist.length_sec.unwrap() + 1.0; } - let mut media = Media::new(0, String::new(), false); + let mut media = Media::new(0, "", false); media.begin = Some(current_time); media.duration = duration; media.out = duration; @@ -357,7 +357,7 @@ impl Iterator for CurrentProgram { // Test if playlist is to early finish, // and if we have to fill it with a placeholder. let index = self.index.load(Ordering::SeqCst); - self.current_node = Media::new(index, String::new(), false); + self.current_node = Media::new(index, "", false); self.current_node.begin = Some(get_sec()); let mut duration = total_delta.abs(); @@ -454,7 +454,7 @@ fn timed_source( } /// Generate the source CMD, or when clip not exist, get a dummy. -fn gen_source( +pub fn gen_source( config: &PlayoutConfig, mut node: Media, filter_chain: &Arc>>, diff --git a/ffplayout-engine/src/lib.rs b/ffplayout-engine/src/lib.rs new file mode 100644 index 00000000..6defb246 --- /dev/null +++ b/ffplayout-engine/src/lib.rs @@ -0,0 +1,4 @@ +pub mod input; +pub mod output; +pub mod rpc; +pub mod utils; diff --git a/ffplayout-engine/src/main.rs b/ffplayout-engine/src/main.rs index 4cf40b91..d669db2e 100644 --- a/ffplayout-engine/src/main.rs +++ b/ffplayout-engine/src/main.rs @@ -12,27 +12,19 @@ use serde::{Deserialize, Serialize}; use serde_json::json; use simplelog::*; -pub mod input; -pub mod output; -pub mod rpc; -// #[cfg(test)] -// mod tests; -pub mod utils; - -use utils::{arg_parse::get_args, get_config}; - -use crate::{ +use ffplayout::{ output::{player, write_hls}, rpc::json_rpc_server, + utils::{arg_parse::get_args, get_config}, }; use ffplayout_lib::utils::{ - generate_playlist, init_logging, send_mail, validate_ffmpeg, PlayerControl, PlayoutStatus, - ProcessControl, + generate_playlist, import::import_file, init_logging, send_mail, validate_ffmpeg, + OutputMode::*, PlayerControl, PlayoutStatus, ProcessControl, }; #[cfg(debug_assertions)] -use utils::Args; +use ffplayout::utils::Args; #[cfg(debug_assertions)] use ffplayout_lib::utils::{mock_time, time_now}; @@ -90,10 +82,11 @@ fn fake_time(args: &Args) { fn main() { let args = get_args(); + // use fake time function only in debugging mode #[cfg(debug_assertions)] fake_time(&args); - let config = get_config(args); + let config = get_config(args.clone()); let config_clone = config.clone(); let play_control = PlayerControl::new(); let playout_stat = PlayoutStatus::new(); @@ -122,6 +115,26 @@ fn main() { exit(0); } + if let Some(path) = args.import { + if args.date.is_none() { + error!("Import needs date parameter!"); + + exit(1); + } + + // convert text/m3u file to playlist + match import_file(&config, &args.date.unwrap(), None, &path) { + Ok(m) => { + info!("{m}"); + exit(0); + } + Err(e) => { + error!("{e}"); + exit(1); + } + } + } + if config.rpc_server.enable { // If RPC server is enable we also fire up a JSON RPC server. thread::spawn(move || json_rpc_server(config_clone, play_ctl, play_stat, proc_ctl2)); @@ -129,9 +142,9 @@ fn main() { status_file(&config.general.stat_file, &playout_stat); - match config.out.mode.to_lowercase().as_str() { + match config.out.mode { // write files/playlist to HLS m3u8 playlist - "hls" => write_hls(&config, play_control, playout_stat, proc_control), + HLS => write_hls(&config, play_control, playout_stat, proc_control), // play on desktop or stream to a remote target _ => player(&config, play_control, playout_stat, proc_control), } diff --git a/ffplayout-engine/src/output/hls.rs b/ffplayout-engine/src/output/hls.rs index af4d428c..4cc57152 100644 --- a/ffplayout-engine/src/output/hls.rs +++ b/ffplayout-engine/src/output/hls.rs @@ -28,10 +28,11 @@ use std::{ use simplelog::*; use crate::input::{ingest::log_line, source_generator}; +use crate::utils::prepare_output_cmd; use ffplayout_lib::filter::filter_chains; use ffplayout_lib::utils::{ - prepare_output_cmd, sec_to_time, stderr_reader, test_tcp_port, Decoder, Ingest, Media, - PlayerControl, PlayoutConfig, PlayoutStatus, ProcessControl, + sec_to_time, stderr_reader, test_tcp_port, Encoder, Ingest, Media, PlayerControl, + PlayoutConfig, PlayoutStatus, ProcessControl, }; use ffplayout_lib::vec_strings; @@ -47,7 +48,7 @@ fn ingest_to_hls_server( let mut server_prefix = vec_strings!["-hide_banner", "-nostats", "-v", "level+info"]; let stream_input = config.ingest.input_cmd.clone().unwrap(); server_prefix.append(&mut stream_input.clone()); - let mut dummy_media = Media::new(0, "Live Stream".to_string(), false); + let mut dummy_media = Media::new(0, "Live Stream", false); dummy_media.is_live = Some(true); let mut is_running; @@ -79,12 +80,7 @@ fn ingest_to_hls_server( } } - let server_cmd = prepare_output_cmd( - server_prefix.clone(), - filters, - config.out.clone().output_cmd.unwrap(), - "hls", - ); + let server_cmd = prepare_output_cmd(server_prefix.clone(), filters, &config); debug!( "Server CMD: \"ffmpeg {}\"", @@ -124,7 +120,7 @@ fn ingest_to_hls_server( info!("Switch from {} to live ingest", config.processing.mode); - if let Err(e) = proc_control.kill(Decoder) { + if let Err(e) = proc_control.kill(Encoder) { error!("{e}"); } } @@ -200,12 +196,7 @@ pub fn write_hls( let mut enc_prefix = vec_strings!["-hide_banner", "-nostats", "-v", &ff_log_format]; enc_prefix.append(&mut cmd); let enc_filter = node.filter.unwrap(); - let enc_cmd = prepare_output_cmd( - enc_prefix, - enc_filter, - config.out.clone().output_cmd.unwrap(), - &config.out.mode, - ); + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, config); debug!( "HLS writer CMD: \"ffmpeg {}\"", @@ -218,20 +209,20 @@ pub fn write_hls( .spawn() { Err(e) => { - error!("couldn't spawn decoder process: {e}"); - panic!("couldn't spawn decoder process: {e}") + error!("couldn't spawn encoder process: {e}"); + panic!("couldn't spawn encoder process: {e}") } Ok(proc) => proc, }; - let dec_err = BufReader::new(enc_proc.stderr.take().unwrap()); - *proc_control.decoder_term.lock().unwrap() = Some(enc_proc); + let enc_err = BufReader::new(enc_proc.stderr.take().unwrap()); + *proc_control.encoder_term.lock().unwrap() = Some(enc_proc); - if let Err(e) = stderr_reader(dec_err, "Writer", proc_control.clone()) { + if let Err(e) = stderr_reader(enc_err, "Writer", proc_control.clone()) { error!("{e:?}") }; - if let Err(e) = proc_control.wait(Decoder) { + if let Err(e) = proc_control.wait(Encoder) { error!("{e}"); } diff --git a/ffplayout-engine/src/output/mod.rs b/ffplayout-engine/src/output/mod.rs index 91855671..e4c81714 100644 --- a/ffplayout-engine/src/output/mod.rs +++ b/ffplayout-engine/src/output/mod.rs @@ -18,8 +18,8 @@ pub use hls::write_hls; use crate::input::{ingest_server, source_generator}; use ffplayout_lib::utils::{ - sec_to_time, stderr_reader, Decoder, PlayerControl, PlayoutConfig, PlayoutStatus, - ProcessControl, + sec_to_time, stderr_reader, Decoder, OutputMode::*, PlayerControl, PlayoutConfig, + PlayoutStatus, ProcessControl, }; use ffplayout_lib::vec_strings; @@ -54,10 +54,10 @@ pub fn player( ); // get ffmpeg output instance - let mut enc_proc = match config.out.mode.as_str() { - "desktop" => desktop::output(config, &ff_log_format), - "null" => null::output(config, &ff_log_format), - "stream" => stream::output(config, &ff_log_format), + let mut enc_proc = match config.out.mode { + Desktop => desktop::output(config, &ff_log_format), + Null => null::output(config, &ff_log_format), + Stream => stream::output(config, &ff_log_format), _ => panic!("Output mode doesn't exists!"), }; diff --git a/ffplayout-engine/src/output/stream.rs b/ffplayout-engine/src/output/stream.rs index 4b9cd9b7..c3ef86eb 100644 --- a/ffplayout-engine/src/output/stream.rs +++ b/ffplayout-engine/src/output/stream.rs @@ -5,8 +5,9 @@ use std::{ use simplelog::*; +use crate::utils::prepare_output_cmd; use ffplayout_lib::filter::v_drawtext; -use ffplayout_lib::utils::{prepare_output_cmd, PlayoutConfig}; +use ffplayout_lib::utils::PlayoutConfig; use ffplayout_lib::vec_strings; /// Streaming Output @@ -46,7 +47,7 @@ pub fn output(config: &PlayoutConfig, log_format: &str) -> process::Child { enc_cmd.append(&mut output_cmd); - let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, enc_cmd, &config.out.mode); + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, config); debug!( "Encoder CMD: \"ffmpeg {}\"", diff --git a/ffplayout-engine/src/rpc/mod.rs b/ffplayout-engine/src/rpc/mod.rs index cf2653b4..ad41bda7 100644 --- a/ffplayout-engine/src/rpc/mod.rs +++ b/ffplayout-engine/src/rpc/mod.rs @@ -13,7 +13,7 @@ use simplelog::*; use ffplayout_lib::utils::{ get_delta, get_filter_from_json, get_sec, sec_to_time, write_status, Ingest, Media, - PlayerControl, PlayoutConfig, PlayoutStatus, ProcessControl, + OutputMode::*, PlayerControl, PlayoutConfig, PlayoutStatus, ProcessControl, }; use zmq_cmd::zmq_send; @@ -85,12 +85,12 @@ pub fn json_rpc_server( { let filter = get_filter_from_json(map["message"].to_string()); - // TODO: in Rust 1.64 use let_chains instead + // TODO: in Rust 1.65 use let_chains instead if !filter.is_empty() && config.text.zmq_stream_socket.is_some() { let mut clips_filter = playout_stat.chain.lock().unwrap(); *clips_filter = vec![filter.clone()]; - if config.out.mode == "hls" { + if config.out.mode == HLS { if proc.server_is_running.load(Ordering::SeqCst) { let filter_server = format!( "Parsed_drawtext_{} reinit {filter}", @@ -108,7 +108,7 @@ pub fn json_rpc_server( } } - if config.out.mode != "hls" || !proc.server_is_running.load(Ordering::SeqCst) { + if config.out.mode != HLS || !proc.server_is_running.load(Ordering::SeqCst) { let filter_stream = format!( "Parsed_drawtext_{} reinit {filter}", playout_stat.drawtext_stream_index.load(Ordering::SeqCst) diff --git a/ffplayout-engine/src/utils/arg_parse.rs b/ffplayout-engine/src/utils/arg_parse.rs index 41c51c8f..bf349bd5 100644 --- a/ffplayout-engine/src/utils/arg_parse.rs +++ b/ffplayout-engine/src/utils/arg_parse.rs @@ -1,5 +1,7 @@ use clap::Parser; +use ffplayout_lib::utils::{OutputMode, ProcessMode}; + #[derive(Parser, Debug, Clone)] #[clap(version, about = "ffplayout, Rust based 24/7 playout solution.", @@ -26,11 +28,24 @@ pub struct Args { pub generate: Option>, #[clap(short = 'm', long, help = "Playing mode: folder, playlist")] - pub play_mode: Option, + pub play_mode: Option, #[clap(short, long, help = "Play folder content")] pub folder: Option, + #[clap( + short, + long, + help = "Target date (YYYY-MM-DD) for text/m3u to playlist import" + )] + pub date: Option, + + #[clap( + long, + help = "Import a given text/m3u file and create a playlist from it" + )] + pub import: Option, + #[clap(short, long, help = "Path from playlist")] pub playlist: Option, @@ -51,8 +66,8 @@ pub struct Args { #[clap(short, long, help = "Loop playlist infinitely")] pub infinit: bool, - #[clap(short, long, help = "Set output mode: desktop, hls, stream")] - pub output: Option, + #[clap(short, long, help = "Set output mode: desktop, hls, null, stream")] + pub output: Option, #[clap(short, long, help = "Set audio volume")] pub volume: Option, diff --git a/ffplayout-engine/src/utils/mod.rs b/ffplayout-engine/src/utils/mod.rs index 44a5baba..e8c0a11f 100644 --- a/ffplayout-engine/src/utils/mod.rs +++ b/ffplayout-engine/src/utils/mod.rs @@ -3,11 +3,17 @@ use std::{ process::exit, }; +use regex::Regex; + pub mod arg_parse; pub use arg_parse::Args; -use ffplayout_lib::utils::{time_to_sec, PlayoutConfig}; +use ffplayout_lib::{ + utils::{time_to_sec, OutputMode::*, PlayoutConfig, ProcessMode::*}, + vec_strings, +}; +/// Read command line arguments, and override the config with them. pub fn get_config(args: Args) -> PlayoutConfig { let cfg_path = match args.channel { Some(c) => { @@ -48,7 +54,7 @@ pub fn get_config(args: Args) -> PlayoutConfig { if let Some(folder) = args.folder { config.storage.path = folder; - config.processing.mode = "folder".into(); + config.processing.mode = Folder; } if let Some(start) = args.start { @@ -80,4 +86,130 @@ pub fn get_config(args: Args) -> PlayoutConfig { config } -// Read command line arguments, and override the config with them. + +/// Prepare output parameters +/// +/// seek for multiple outputs and add mapping for it +pub fn prepare_output_cmd( + mut cmd: Vec, + mut filter: Vec, + config: &PlayoutConfig, +) -> Vec { + let mut output_params = config.out.clone().output_cmd.unwrap(); + let mut new_params = vec![]; + let params_len = output_params.len(); + let mut output_a_map = "[a_out1]".to_string(); + let mut output_v_map = "[v_out1]".to_string(); + let mut out_count = 1; + let mut output_filter = String::new(); + let mut next_is_filter = false; + let re_audio_map = Regex::new(r"\[0:a:(?P[0-9]+)\]").unwrap(); + + // Loop over output parameters + // + // Check if it contains a filtergraph, count its outputs and set correct mapping values. + for (i, p) in output_params.iter().enumerate() { + let mut param = p.clone(); + + param = param.replace("[0:v]", "[vout0]"); + param = param.replace("[0:a]", "[aout0]"); + param = re_audio_map.replace_all(¶m, "[aout$num]").to_string(); + + // Skip filter command, to concat existing filters with new ones. + if param != "-filter_complex" { + if next_is_filter { + output_filter = param.clone(); + next_is_filter = false; + } else { + new_params.push(param.clone()); + } + } else { + next_is_filter = true; + } + + // Check if parameter is a output + if i > 0 + && !param.starts_with('-') + && !output_params[i - 1].starts_with('-') + && i < params_len - 1 + { + out_count += 1; + let mut a_map = "0:a".to_string(); + let v_map = format!("[v_out{out_count}]"); + output_v_map.push_str(&v_map); + + if config.out.mode == HLS { + a_map = format!("[a_out{out_count}]"); + } + + output_a_map.push_str(&a_map); + + if !output_params.contains(&"-map".to_string()) { + let mut map = vec_strings!["-map", v_map, "-map", a_map]; + new_params.append(&mut map); + } + } + } + + if !filter.is_empty() { + output_params = new_params; + + // Process A/V mapping + // + // Check if there is multiple outputs, and/or multiple audio tracks + // and add the correct mapping for it. + if out_count > 1 && config.processing.audio_tracks == 1 && config.out.mode == HLS { + filter[1].push_str(&format!(";[vout0]split={out_count}{output_v_map}")); + filter[1].push_str(&format!(";[aout0]asplit={out_count}{output_a_map}")); + filter.drain(2..); + cmd.append(&mut filter); + cmd.append(&mut vec_strings!["-map", "[v_out1]", "-map", "[a_out1]"]); + } else if !output_filter.is_empty() && config.out.mode == HLS { + filter[1].push_str(&format!(";{output_filter}")); + filter.drain(2..); + cmd.append(&mut filter); + } else if out_count == 1 + && config.processing.audio_tracks == 1 + && config.out.mode == HLS + && output_params[0].contains("split") + { + let out_filter = output_params.remove(0); + filter[1].push_str(&format!(";{out_filter}")); + filter.drain(2..); + cmd.append(&mut filter); + } else if out_count > 1 && config.processing.audio_tracks == 1 && config.out.mode == Stream + { + filter[1].push_str(&format!(",split={out_count}{output_v_map}")); + cmd.append(&mut filter); + cmd.append(&mut vec_strings!["-map", "[v_out1]", "-map", "0:a"]); + } else if config.processing.audio_tracks > 1 && config.out.mode == Stream { + filter[1].push_str("[v_out1]"); + cmd.append(&mut filter); + + output_params = output_params + .iter() + .map(|p| p.replace("0:v", "[v_out1]")) + .collect(); + + if out_count == 1 { + cmd.append(&mut vec_strings!["-map", "[v_out1]"]); + + for i in 0..config.processing.audio_tracks { + cmd.append(&mut vec_strings!["-map", format!("0:a:{i}")]); + } + } + } else { + cmd.append(&mut filter); + } + } else if out_count == 1 && config.processing.audio_tracks > 1 && config.out.mode == Stream { + cmd.append(&mut vec_strings!["-map", "0:v"]); + + for i in 0..config.processing.audio_tracks { + cmd.append(&mut vec_strings!["-map", format!("0:a:{i}")]); + } + } + + cmd.append(&mut output_params); + + cmd +} diff --git a/ffplayout-frontend b/ffplayout-frontend index 51719eb9..0994fd00 160000 --- a/ffplayout-frontend +++ b/ffplayout-frontend @@ -1 +1 @@ -Subproject commit 51719eb9c03d26da8ffac6a677d1c41b756bdf83 +Subproject commit 0994fd00d16354b3d3059e8e3fae2ed256264460 diff --git a/lib/Cargo.toml b/lib/Cargo.toml index a8ae099c..2a99e6d9 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -4,7 +4,7 @@ description = "Library for ffplayout" license = "GPL-3.0" authors = ["Jonathan Baecker jonbae77@gmail.com"] readme = "README.md" -version = "0.15.2" +version = "0.16.0" edition = "2021" [dependencies] diff --git a/lib/src/filter/mod.rs b/lib/src/filter/mod.rs index c5d22692..287e9844 100644 --- a/lib/src/filter/mod.rs +++ b/lib/src/filter/mod.rs @@ -1,85 +1,140 @@ use std::{ + fmt, path::Path, sync::{Arc, Mutex}, }; use simplelog::*; -pub mod a_loudnorm; -pub mod custom_filter; +mod a_loudnorm; +mod custom_filter; pub mod v_drawtext; -pub mod v_overlay; -use crate::utils::{fps_calc, get_delta, is_close, Media, MediaProbe, PlayoutConfig}; +// get_delta +use self::custom_filter::custom_filter; +use crate::utils::{ + fps_calc, get_delta, is_close, Media, MediaProbe, OutputMode::*, PlayoutConfig, +}; -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Debug, Copy, PartialEq)] enum FilterType { Audio, Video, } -use FilterType::*; +impl fmt::Display for FilterType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + FilterType::Audio => write!(f, "a"), + FilterType::Video => write!(f, "v"), + } + } +} -use self::custom_filter::custom_filter; +use FilterType::*; #[derive(Debug, Clone)] struct Filters { - audio_chain: Option, - video_chain: Option, - audio_map: String, - video_map: String, + audio_chain: String, + video_chain: String, + final_chain: String, + audio_map: Vec, + video_map: Vec, + output_map: Vec, + audio_position: i32, + video_position: i32, + audio_last: i32, + video_last: i32, + cmd: Vec, } impl Filters { - fn new() -> Self { - Filters { - audio_chain: None, - video_chain: None, - audio_map: "0:a".to_string(), - video_map: "0:v".to_string(), + fn new(position: i32) -> Self { + Self { + audio_chain: String::new(), + video_chain: String::new(), + final_chain: String::new(), + audio_map: vec![], + video_map: vec![], + output_map: vec![], + audio_position: position, + video_position: position, + audio_last: -1, + video_last: -1, + cmd: vec![], } } - fn add_filter(&mut self, filter: &str, codec_type: FilterType) { - match codec_type { - Audio => match &self.audio_chain { - Some(ac) => { - if filter.starts_with(';') || filter.starts_with('[') { - self.audio_chain = Some(format!("{ac}{filter}")) - } else { - self.audio_chain = Some(format!("{ac},{filter}")) - } - } - None => { - if filter.contains("aevalsrc") || filter.contains("anoisesrc") { - self.audio_chain = Some(filter.to_string()); - } else { - self.audio_chain = Some(format!("[{}]{filter}", self.audio_map.clone())); - } - self.audio_map = "[aout1]".to_string(); - } - }, - Video => match &self.video_chain { - Some(vc) => { - if filter.starts_with(';') || filter.starts_with('[') { - self.video_chain = Some(format!("{vc}{filter}")) - } else { - self.video_chain = Some(format!("{vc},{filter}")) - } - } - None => { - self.video_chain = Some(format!("[0:v]{filter}")); - self.video_map = "[vout1]".to_string(); - } - }, + fn add_filter(&mut self, filter: &str, track_nr: i32, filter_type: FilterType) { + let (map, chain, position, last) = match filter_type { + Audio => ( + &mut self.audio_map, + &mut self.audio_chain, + self.audio_position, + &mut self.audio_last, + ), + Video => ( + &mut self.video_map, + &mut self.video_chain, + self.video_position, + &mut self.video_last, + ), + }; + + if *last != track_nr { + // start new filter chain + let mut selector = String::new(); + let mut sep = String::new(); + if !chain.is_empty() { + selector = format!("[{}out{}]", filter_type, last); + sep = ";".to_string() + } + + chain.push_str(&selector); + + if filter.starts_with("aevalsrc") || filter.starts_with("movie") { + chain.push_str(&format!("{sep}{filter}")); + } else { + chain.push_str(&format!( + "{sep}[{}:{}:{track_nr}]{filter}", + position, filter_type + )); + } + + let m = format!("[{}out{track_nr}]", filter_type); + map.push(m.clone()); + self.output_map.append(&mut vec!["-map".to_string(), m]); + *last = track_nr; + } else if filter.starts_with(';') || filter.starts_with('[') { + chain.push_str(filter); + } else { + chain.push_str(&format!(",{filter}")) } } + + fn close_chains(&mut self) { + // add final output selector + self.audio_chain + .push_str(&format!("[aout{}]", self.audio_last)); + self.video_chain + .push_str(&format!("[vout{}]", self.video_last)); + } + + fn build_final_chain(&mut self) { + self.final_chain.push_str(&self.video_chain); + self.final_chain.push(';'); + self.final_chain.push_str(&self.audio_chain); + + self.cmd.push("-filter_complex".to_string()); + self.cmd.push(self.final_chain.clone()); + self.cmd.append(&mut self.output_map); + } } fn deinterlace(field_order: &Option, chain: &mut Filters) { if let Some(order) = field_order { if order != "progressive" { - chain.add_filter("yadif=0:-1:0", Video) + chain.add_filter("yadif=0:-1:0", 0, Video) } } } @@ -100,6 +155,7 @@ fn pad(aspect: f64, chain: &mut Filters, v_stream: &ffprobe::Stream, config: &Pl "{scale}pad=max(iw\\,ih*({0}/{1})):ow/({0}/{1}):(ow-iw)/2:(oh-ih)/2", config.processing.width, config.processing.height ), + 0, Video, ) } @@ -107,7 +163,7 @@ fn pad(aspect: f64, chain: &mut Filters, v_stream: &ffprobe::Stream, config: &Pl fn fps(fps: f64, chain: &mut Filters, config: &PlayoutConfig) { if fps != config.processing.fps { - chain.add_filter(&format!("fps={}", config.processing.fps), Video) + chain.add_filter(&format!("fps={}", config.processing.fps), 0, Video) } } @@ -126,14 +182,19 @@ fn scale( "scale={}:{}", config.processing.width, config.processing.height ), + 0, Video, ); } else { - chain.add_filter("null", Video); + chain.add_filter("null", 0, Video); } if !is_close(aspect, config.processing.aspect, 0.03) { - chain.add_filter(&format!("setdar=dar={}", config.processing.aspect), Video) + chain.add_filter( + &format!("setdar=dar={}", config.processing.aspect), + 0, + Video, + ) } } else { chain.add_filter( @@ -141,27 +202,33 @@ fn scale( "scale={}:{}", config.processing.width, config.processing.height ), + 0, Video, ); - chain.add_filter(&format!("setdar=dar={}", config.processing.aspect), Video) + chain.add_filter( + &format!("setdar=dar={}", config.processing.aspect), + 0, + Video, + ) } } -fn fade(node: &mut Media, chain: &mut Filters, codec_type: FilterType) { +fn fade(node: &mut Media, chain: &mut Filters, nr: i32, filter_type: FilterType) { let mut t = ""; - if codec_type == Audio { + if filter_type == Audio { t = "a" } if node.seek > 0.0 || node.is_live == Some(true) { - chain.add_filter(&format!("{t}fade=in:st=0:d=0.5"), codec_type) + chain.add_filter(&format!("{t}fade=in:st=0:d=0.5"), nr, filter_type) } if node.out != node.duration && node.out - node.seek - 1.0 > 0.0 { chain.add_filter( &format!("{t}fade=out:st={}:d=1.0", (node.out - node.seek - 1.0)), - codec_type, + nr, + filter_type, ) } } @@ -171,7 +238,10 @@ fn overlay(node: &mut Media, chain: &mut Filters, config: &PlayoutConfig) { && Path::new(&config.processing.logo).is_file() && &node.category != "advertisement" { - let mut logo_chain = v_overlay::filter_node(config, false); + let mut logo_chain = format!( + "null[v];movie={}:loop=0,setpts=N/(FRAME_RATE*TB),format=rgba,colorchannelmixer=aa={}[l];[v][l]{}:shortest=1", + config.processing.logo, config.processing.logo_opacity, config.processing.logo_filter + ); if node.last_ad.unwrap_or(false) { logo_chain.push_str(",fade=in:st=0:d=1.0:alpha=1") @@ -183,10 +253,7 @@ fn overlay(node: &mut Media, chain: &mut Filters, config: &PlayoutConfig) { ) } - logo_chain - .push_str(format!("[l];[v][l]{}:shortest=1", config.processing.logo_filter).as_str()); - - chain.add_filter(&logo_chain, Video); + chain.add_filter(&logo_chain, 0, Video); } } @@ -204,6 +271,7 @@ fn extend_video(node: &mut Media, chain: &mut Filters) { "tpad=stop_mode=add:stop_duration={}", (node.out - node.seek) - (video_duration - node.seek) ), + 0, Video, ) } @@ -217,33 +285,22 @@ fn add_text( config: &PlayoutConfig, filter_chain: &Arc>>, ) { - if config.text.add_text - && (config.text.text_from_filename || config.out.mode.to_lowercase() == "hls") - { + if config.text.add_text && (config.text.text_from_filename || config.out.mode == HLS) { let filter = v_drawtext::filter_node(config, Some(node), filter_chain); - chain.add_filter(&filter, Video); + chain.add_filter(&filter, 0, Video); } } -fn add_audio(node: &mut Media, chain: &mut Filters) { - if node - .probe - .as_ref() - .and_then(|p| p.audio_streams.get(0)) - .is_none() - && !Path::new(&node.audio).is_file() - { - warn!("Clip {} has no audio!", node.source); - let audio = format!( - "aevalsrc=0:channel_layout=stereo:duration={}:sample_rate=48000", - node.out - node.seek - ); - chain.add_filter(&audio, Audio); - } +fn add_audio(node: &Media, chain: &mut Filters, nr: i32) { + let audio = format!( + "aevalsrc=0:channel_layout=stereo:duration={}:sample_rate=48000", + node.out - node.seek + ); + chain.add_filter(&audio, nr, Audio); } -fn extend_audio(node: &mut Media, chain: &mut Filters) { +fn extend_audio(node: &mut Media, chain: &mut Filters, nr: i32) { let probe = if Path::new(&node.audio).is_file() { Some(MediaProbe::new(&node.audio)) } else { @@ -257,22 +314,26 @@ fn extend_audio(node: &mut Media, chain: &mut Filters) { .and_then(|a| a.parse::().ok()) { if node.out - node.seek > audio_duration - node.seek + 0.1 && node.duration >= node.out { - chain.add_filter(&format!("apad=whole_dur={}", node.out - node.seek), Audio) + chain.add_filter( + &format!("apad=whole_dur={}", node.out - node.seek), + nr, + Audio, + ) } } } /// Add single pass loudnorm filter to audio line. -fn add_loudnorm(chain: &mut Filters, config: &PlayoutConfig) { +fn add_loudnorm(chain: &mut Filters, config: &PlayoutConfig, nr: i32) { if config.processing.add_loudnorm { let loud_filter = a_loudnorm::filter_node(config); - chain.add_filter(&loud_filter, Audio); + chain.add_filter(&loud_filter, nr, Audio); } } -fn audio_volume(chain: &mut Filters, config: &PlayoutConfig) { +fn audio_volume(chain: &mut Filters, config: &PlayoutConfig, nr: i32) { if config.processing.volume != 1.0 { - chain.add_filter(&format!("volume={}", config.processing.volume), Audio) + chain.add_filter(&format!("volume={}", config.processing.volume), nr, Audio) } } @@ -290,20 +351,9 @@ fn aspect_calc(aspect_string: &Option, config: &PlayoutConfig) -> f64 { } /// This realtime filter is important for HLS output to stay in sync. -fn realtime_filter( - node: &mut Media, - chain: &mut Filters, - config: &PlayoutConfig, - codec_type: FilterType, -) { - if config.general.generate.is_none() && &config.out.mode.to_lowercase() == "hls" { - let mut t = ""; - - if codec_type == Audio { - t = "a" - } - - let mut speed_filter = format!("{t}realtime=speed=1"); +fn realtime(node: &mut Media, chain: &mut Filters, config: &PlayoutConfig) { + if config.general.generate.is_none() && config.out.mode == HLS { + let mut speed_filter = "realtime=speed=1".to_string(); if let Some(begin) = &node.begin { let (delta, _) = get_delta(config, begin); @@ -313,24 +363,18 @@ fn realtime_filter( let speed = duration / (duration + delta); if speed > 0.0 && speed < 1.1 && delta < config.general.stop_threshold { - speed_filter = format!("{t}realtime=speed={speed}"); + speed_filter = format!("realtime=speed={speed}"); } } } - chain.add_filter(&speed_filter, codec_type); + chain.add_filter(&speed_filter, 0, Video); } } -fn custom(filter: &str, chain: &mut Filters) { - let (video_filter, audio_filter) = custom_filter(filter); - - if !video_filter.is_empty() { - chain.add_filter(&video_filter, Video); - } - - if !audio_filter.is_empty() { - chain.add_filter(&audio_filter, Audio); +fn custom(filter: &str, chain: &mut Filters, nr: i32, filter_type: FilterType) { + if !filter.is_empty() { + chain.add_filter(filter, nr, filter_type); } } @@ -339,11 +383,11 @@ pub fn filter_chains( node: &mut Media, filter_chain: &Arc>>, ) -> Vec { - let mut filters = Filters::new(); + let mut filters = Filters::new(0); if let Some(probe) = node.probe.as_ref() { - if probe.audio_streams.get(0).is_none() || Path::new(&node.audio).is_file() { - filters.audio_map = "1:a".to_string(); + if Path::new(&node.audio).is_file() { + filters.audio_position = 1; } if let Some(v_stream) = &probe.video_streams.get(0) { @@ -363,56 +407,51 @@ pub fn filter_chains( } extend_video(node, &mut filters); - - add_audio(node, &mut filters); - extend_audio(node, &mut filters); } else { fps(0.0, &mut filters, config); scale(None, None, 1.0, &mut filters, config); } add_text(node, &mut filters, config, filter_chain); - fade(node, &mut filters, Video); + fade(node, &mut filters, 0, Video); overlay(node, &mut filters, config); - realtime_filter(node, &mut filters, config, Video); + realtime(node, &mut filters, config); - add_loudnorm(&mut filters, config); - fade(node, &mut filters, Audio); - audio_volume(&mut filters, config); - realtime_filter(node, &mut filters, config, Audio); + let (proc_vf, proc_af) = custom_filter(&config.processing.custom_filter); + let (list_vf, list_af) = custom_filter(&node.custom_filter); - custom(&config.processing.custom_filter, &mut filters); - custom(&node.custom_filter, &mut filters); + custom(&proc_vf, &mut filters, 0, Video); + custom(&list_vf, &mut filters, 0, Video); - let mut filter_cmd = vec![]; - let mut filter_str: String = String::new(); - let mut filter_map: Vec = vec![]; - - if let Some(v_filters) = filters.video_chain { - filter_str.push_str(v_filters.as_str()); - filter_str.push_str(filters.video_map.clone().as_str()); - filter_map.append(&mut vec!["-map".to_string(), filters.video_map]); - } else { - filter_map.append(&mut vec!["-map".to_string(), "0:v".to_string()]); - } - - if let Some(a_filters) = filters.audio_chain { - if filter_str.len() > 10 { - filter_str.push(';') + for i in 0..config.processing.audio_tracks { + if node + .probe + .as_ref() + .and_then(|p| p.audio_streams.get(i as usize)) + .is_some() + { + extend_audio(node, &mut filters, i); + } else if !node.is_live.unwrap_or(false) { + warn!( + "Missing audio track (id {i}) from {}", + node.source + ); + add_audio(node, &mut filters, i); } - filter_str.push_str(a_filters.as_str()); - filter_str.push_str(filters.audio_map.clone().as_str()); - filter_map.append(&mut vec!["-map".to_string(), filters.audio_map]); - } else { - filter_map.append(&mut vec!["-map".to_string(), filters.audio_map]); + // add at least anull filter, for correct filter construction, + // is important for split filter in HLS mode + filters.add_filter("anull", i, Audio); + + add_loudnorm(&mut filters, config, i); + fade(node, &mut filters, i, Audio); + audio_volume(&mut filters, config, i); + + custom(&proc_af, &mut filters, i, Audio); + custom(&list_af, &mut filters, i, Audio); } - if filter_str.len() > 10 { - filter_cmd.push("-filter_complex".to_string()); - filter_cmd.push(filter_str); - } + filters.close_chains(); + filters.build_final_chain(); - filter_cmd.append(&mut filter_map); - - filter_cmd + filters.cmd } diff --git a/lib/src/filter/v_drawtext.rs b/lib/src/filter/v_drawtext.rs index e93bd7ed..88c551f6 100644 --- a/lib/src/filter/v_drawtext.rs +++ b/lib/src/filter/v_drawtext.rs @@ -26,12 +26,9 @@ pub fn filter_node( None => config.text.zmq_stream_socket.clone(), }; - // TODO: in Rust 1.64 use let_chains instead + // TODO: in Rust 1.65 use let_chains instead if config.text.text_from_filename && node.is_some() { - let source = node - .unwrap_or(&Media::new(0, String::new(), false)) - .source - .clone(); + let source = node.unwrap_or(&Media::new(0, "", false)).source.clone(); let regex: Regex = Regex::new(&config.text.regex).unwrap(); let text: String = match regex.captures(&source) { diff --git a/lib/src/filter/v_overlay.rs b/lib/src/filter/v_overlay.rs deleted file mode 100644 index ff122310..00000000 --- a/lib/src/filter/v_overlay.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::utils::PlayoutConfig; - -/// Overlay Filter -/// -/// When a logo is set, we create here the filter for the server. -pub fn filter_node(config: &PlayoutConfig, add_tail: bool) -> String { - let mut logo_chain = String::new(); - - if !config.processing.add_logo { - return logo_chain; - } - - if let Some(fps) = config.processing.logo_fps { - let opacity = format!( - "format=rgba,colorchannelmixer=aa={}", - config.processing.logo_opacity - ); - let pts = format!("setpts=N/({fps}*TB)"); - logo_chain = format!( - "null[v];movie={}:loop=0,{pts},{opacity}", - config.processing.logo - ); - - if add_tail { - logo_chain.push_str( - format!("[l];[v][l]{}:shortest=1", config.processing.logo_filter).as_str(), - ); - } - }; - - logo_chain -} diff --git a/lib/src/lib.rs b/lib/src/lib.rs index da112113..f01731e7 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -4,6 +4,3 @@ extern crate simplelog; pub mod filter; pub mod macros; pub mod utils; - -#[cfg(test)] -mod tests; diff --git a/lib/src/tests/mod.rs b/lib/src/tests/mod.rs deleted file mode 100644 index f50cd743..00000000 --- a/lib/src/tests/mod.rs +++ /dev/null @@ -1,116 +0,0 @@ -#[cfg(test)] -use chrono::prelude::*; - -#[cfg(test)] -use crate::utils::*; -use crate::vec_strings; - -#[test] -fn mock_date_time() { - let time_str = "2022-05-20T06:00:00"; - let date_obj = NaiveDateTime::parse_from_str(time_str, "%Y-%m-%dT%H:%M:%S"); - let time = Local.from_local_datetime(&date_obj.unwrap()).unwrap(); - - mock_time::set_mock_time(time_str); - - assert_eq!( - time.format("%Y-%m-%dT%H:%M:%S.2f").to_string(), - time_now().format("%Y-%m-%dT%H:%M:%S.2f").to_string() - ); -} - -#[test] -fn get_date_yesterday() { - mock_time::set_mock_time("2022-05-20T05:59:24"); - - let date = get_date(true, 21600.0, 86400.0); - - assert_eq!("2022-05-19".to_string(), date); -} - -#[test] -fn get_date_tomorrow() { - mock_time::set_mock_time("2022-05-20T23:59:30"); - - let date = get_date(false, 0.0, 86400.01); - - assert_eq!("2022-05-21".to_string(), date); -} - -#[test] -fn test_delta() { - let mut config = PlayoutConfig::new(None); - config.mail.recipient = "".into(); - config.processing.mode = "playlist".into(); - config.playlist.day_start = "00:00:00".into(); - config.playlist.length = "24:00:00".into(); - config.logging.log_to_file = false; - - mock_time::set_mock_time("2022-05-09T23:59:59"); - let (delta, _) = get_delta(&config, &86401.0); - - assert!(delta < 2.0); -} - -#[test] -fn test_prepare_output_cmd() { - let enc_prefix = vec_strings![ - "-hide_banner", - "-nostats", - "-v", - "level+error", - "-re", - "-i", - "pipe:0" - ]; - let filter = vec_strings![ - "-filter_complex", - "[0:v]null,zmq=b=tcp\\\\://'127.0.0.1\\:5555',drawtext=text=''" - ]; - let params = vec_strings![ - "-c:v", - "libx264", - "-flags", - "+global_header", - "-f", - "flv", - "rtmp://localhost/live/stream", - "-s", - "512x288", - "-c:v", - "libx264", - "-flags", - "+global_header", - "-f", - "flv", - "rtmp://localhost:1937/live/stream" - ]; - - let mut t1_params = enc_prefix.clone(); - t1_params.append(&mut params.clone()); - let cmd_two_outs = - prepare_output_cmd(enc_prefix.clone(), vec_strings![], params.clone(), "stream"); - - assert_eq!(cmd_two_outs, t1_params); - - let mut test_cmd = enc_prefix.clone(); - let mut test_params = params.clone(); - let mut t2_filter = filter.clone(); - t2_filter[1].push_str(",split=2[v_out1][v_out2]"); - test_cmd.append(&mut t2_filter); - - test_params.insert(0, "-map".to_string()); - test_params.insert(1, "[v_out1]".to_string()); - test_params.insert(2, "-map".to_string()); - test_params.insert(3, "0:a".to_string()); - - test_params.insert(11, "-map".to_string()); - test_params.insert(12, "[v_out2]".to_string()); - test_params.insert(13, "-map".to_string()); - test_params.insert(14, "0:a".to_string()); - - test_cmd.append(&mut test_params); - let cmd_two_outs_with_filter = prepare_output_cmd(enc_prefix, filter, params, "stream"); - - assert_eq!(cmd_two_outs_with_filter, test_cmd); -} diff --git a/lib/src/utils/config.rs b/lib/src/utils/config.rs index be81ee3b..755a34e4 100644 --- a/lib/src/utils/config.rs +++ b/lib/src/utils/config.rs @@ -1,14 +1,15 @@ use std::{ - env, + env, fmt, fs::File, path::{Path, PathBuf}, process, + str::FromStr, }; use serde::{Deserialize, Serialize}; use shlex::split; -use crate::utils::{fps_calc, free_tcp_socket, home_dir, time_to_sec, MediaProbe}; +use crate::utils::{free_tcp_socket, home_dir, time_to_sec}; use crate::vec_strings; pub const DUMMY_LEN: f64 = 60.0; @@ -17,6 +18,64 @@ pub const IMAGE_FORMAT: [&str; 21] = [ "png", "psd", "ppm", "sgi", "svg", "tga", "tif", "webp", ]; +// Some well known errors can be safely ignore +pub const FFMPEG_IGNORE_ERRORS: [&str; 3] = [ + "Referenced QT chapter track not found", + "ac-tex damaged", + "Warning MVs not available", +]; + +#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum OutputMode { + Desktop, + HLS, + Null, + Stream, +} + +impl FromStr for OutputMode { + type Err = String; + + fn from_str(input: &str) -> Result { + match input { + "desktop" => Ok(Self::Desktop), + "hls" => Ok(Self::HLS), + "null" => Ok(Self::Null), + "stream" => Ok(Self::Stream), + _ => Err(String::new()), + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum ProcessMode { + Folder, + Playlist, +} + +impl fmt::Display for ProcessMode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ProcessMode::Folder => write!(f, "folder"), + ProcessMode::Playlist => write!(f, "playlist"), + } + } +} + +impl FromStr for ProcessMode { + type Err = String; + + fn from_str(input: &str) -> Result { + match input { + "folder" => Ok(Self::Folder), + "playlist" => Ok(Self::Playlist), + _ => Err(String::new()), + } + } +} + /// Global Config /// /// This we init ones, when ffplayout is starting and use them globally in the hole program. @@ -82,20 +141,18 @@ pub struct Logging { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Processing { pub help_text: String, - pub mode: String, + pub mode: ProcessMode, pub width: i64, pub height: i64, pub aspect: f64, pub fps: f64, pub add_logo: bool, pub logo: String, - - #[serde(skip_serializing, skip_deserializing)] - pub logo_fps: Option, - pub logo_scale: String, pub logo_opacity: f32, pub logo_filter: String, + #[serde(default)] + pub audio_tracks: i32, pub add_loudnorm: bool, pub loudnorm_ingest: bool, pub loud_i: f32, @@ -168,7 +225,7 @@ pub struct Text { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Out { pub help_text: String, - pub mode: String, + pub mode: OutputMode, pub output_param: String, #[serde(skip_serializing, skip_deserializing)] @@ -227,17 +284,12 @@ impl PlayoutConfig { config.playlist.length_sec = Some(86400.0); } - config.processing.logo_fps = None; + if config.processing.add_logo && !Path::new(&config.processing.logo).is_file() { + config.processing.add_logo = false; + } - if Path::new(&config.processing.logo).is_file() { - if let Some(v_stream) = MediaProbe::new(&config.processing.logo) - .video_streams - .get(0) - { - let fps = fps_calc(&v_stream.r_frame_rate, config.processing.fps); - - config.processing.logo_fps = Some(fps); - }; + if config.processing.audio_tracks < 1 { + config.processing.audio_tracks = 1 } // We set the decoder settings here, so we only define them ones. diff --git a/lib/src/utils/controller.rs b/lib/src/utils/controller.rs index cede1644..494162b9 100644 --- a/lib/src/utils/controller.rs +++ b/lib/src/utils/controller.rs @@ -92,9 +92,7 @@ impl ProcessControl { } } - if let Err(e) = self.wait(unit) { - return Err(e); - }; + self.wait(unit)?; Ok(()) } @@ -169,7 +167,7 @@ impl PlayerControl { pub fn new() -> Self { Self { current_media: Arc::new(Mutex::new(None)), - current_list: Arc::new(Mutex::new(vec![Media::new(0, String::new(), false)])), + current_list: Arc::new(Mutex::new(vec![Media::new(0, "", false)])), index: Arc::new(AtomicUsize::new(0)), } } diff --git a/lib/src/utils/folder.rs b/lib/src/utils/folder.rs index 2093345e..20006a73 100644 --- a/lib/src/utils/folder.rs +++ b/lib/src/utils/folder.rs @@ -49,7 +49,7 @@ impl FolderSource { .filter(|f| f.path().is_file()) { if include_file(config.clone(), entry.path()) { - let media = Media::new(0, entry.path().display().to_string(), false); + let media = Media::new(0, &entry.path().to_string_lossy(), false); media_list.push(media); } } @@ -83,7 +83,7 @@ impl FolderSource { config: config.clone(), filter_chain, nodes: current_list, - current_node: Media::new(0, String::new(), false), + current_node: Media::new(0, "", false), index: global_index, } } diff --git a/lib/src/utils/generator.rs b/lib/src/utils/generator.rs index 192eaf33..7aa3dbca 100644 --- a/lib/src/utils/generator.rs +++ b/lib/src/utils/generator.rs @@ -65,7 +65,7 @@ pub fn generate_playlist( } } }; - let current_list = Arc::new(Mutex::new(vec![Media::new(0, "".to_string(), false)])); + let current_list = Arc::new(Mutex::new(vec![Media::new(0, "", false)])); let index = Arc::new(AtomicUsize::new(0)); let playlist_root = Path::new(&config.playlist.path); let mut playlists = vec![]; @@ -119,7 +119,7 @@ pub fn generate_playlist( playlist_file.display() ); - let mut filler = Media::new(0, config.storage.filler_clip.clone(), true); + let mut filler = Media::new(0, &config.storage.filler_clip, true); let filler_length = filler.duration; let mut length = 0.0; let mut round = 0; diff --git a/lib/src/utils/import.rs b/lib/src/utils/import.rs new file mode 100644 index 00000000..369ff537 --- /dev/null +++ b/lib/src/utils/import.rs @@ -0,0 +1,78 @@ +/// Import text/m3u file and create a playlist out of it +use std::{ + //error::Error, + fs::{create_dir_all, File}, + io::{BufRead, BufReader, Error, ErrorKind}, + path::Path, +}; + +use crate::utils::{json_reader, json_serializer::JsonPlaylist, json_writer, Media, PlayoutConfig}; + +pub fn import_file( + config: &PlayoutConfig, + date: &str, + channel_name: Option, + path: &str, +) -> Result { + let file = File::open(path)?; + let reader = BufReader::new(file); + let mut playlist = JsonPlaylist { + channel: channel_name.unwrap_or_else(|| "Channel 1".to_string()), + date: date.to_string(), + current_file: None, + start_sec: None, + modified: None, + program: vec![], + }; + + let playlist_root = Path::new(&config.playlist.path); + if !playlist_root.is_dir() { + return Err(Error::new( + ErrorKind::Other, + format!( + "Playlist folder {} not exists!", + &config.playlist.path, + ), + )); + } + + let d: Vec<&str> = date.split('-').collect(); + let year = d[0]; + let month = d[1]; + let playlist_path = playlist_root.join(year).join(month); + let playlist_file = &playlist_path.join(format!("{date}.json")); + + create_dir_all(playlist_path)?; + + for line in reader.lines() { + let line = line?; + + if !line.starts_with('#') { + let item = Media::new(0, &line, true); + + playlist.program.push(item); + } + } + + let mut file_exists = false; + + if playlist_file.is_file() { + file_exists = true; + let existing_data = json_reader(playlist_file)?; + + if playlist == existing_data { + return Ok(format!("Playlist from {date}, already exists!")); + } + }; + + let mut msg = format!("Write playlist from {date} success!"); + + if file_exists { + msg = format!("Update playlist from {date} success!"); + } + + match json_writer(playlist_file, playlist) { + Ok(_) => Ok(msg), + Err(e) => Err(Error::new(ErrorKind::Other, e)), + } +} diff --git a/lib/src/utils/json_serializer.rs b/lib/src/utils/json_serializer.rs index 031b194e..05ccacf2 100644 --- a/lib/src/utils/json_serializer.rs +++ b/lib/src/utils/json_serializer.rs @@ -34,7 +34,7 @@ pub struct JsonPlaylist { impl JsonPlaylist { fn new(date: String, start: f64) -> Self { - let mut media = Media::new(0, String::new(), false); + let mut media = Media::new(0, "", false); media.begin = Some(start); media.duration = DUMMY_LEN; media.out = DUMMY_LEN; diff --git a/lib/src/utils/json_validate.rs b/lib/src/utils/json_validate.rs index 1a0a69a2..2c6185bd 100644 --- a/lib/src/utils/json_validate.rs +++ b/lib/src/utils/json_validate.rs @@ -11,7 +11,7 @@ use simplelog::*; use crate::utils::{ format_log_line, loop_image, sec_to_time, seek_and_length, valid_source, vec_strings, - JsonPlaylist, Media, PlayoutConfig, IMAGE_FORMAT, + JsonPlaylist, Media, PlayoutConfig, FFMPEG_IGNORE_ERRORS, IMAGE_FORMAT, }; /// check if ffmpeg can read the file and apply filter to it. @@ -58,9 +58,7 @@ fn check_media( let mut filter = node.filter.unwrap_or_default(); if filter.len() > 1 { - filter[1] = filter[1] - .replace("realtime=speed=1", "null") - .replace("arealtime=speed=1", "snull") + filter[1] = filter[1].replace("realtime=speed=1", "null") } enc_cmd.append(&mut node.cmd.unwrap_or_default()); @@ -81,24 +79,26 @@ fn check_media( for line in enc_err.lines() { let line = line?; - if line.contains("[error]") { - let log_line = format_log_line(line, "error"); + if !FFMPEG_IGNORE_ERRORS.iter().any(|i| line.contains(*i)) { + if line.contains("[error]") { + let log_line = format_log_line(line, "error"); - if !error_list.contains(&log_line) { - error_list.push(log_line); - } - } else if line.contains("[fatal]") { - let log_line = format_log_line(line, "fatal"); + if !error_list.contains(&log_line) { + error_list.push(log_line); + } + } else if line.contains("[fatal]") { + let log_line = format_log_line(line, "fatal"); - if !error_list.contains(&log_line) { - error_list.push(log_line); + if !error_list.contains(&log_line) { + error_list.push(log_line); + } } } } if !error_list.is_empty() { error!( - "[Validator] Compressing error on position {pos} {}: {}:\n{}", + "[Validator] ffmpeg error on position {pos} - {}: {}:\n{}", sec_to_time(begin), node.source, error_list.join("\n") @@ -107,6 +107,10 @@ fn check_media( error_list.clear(); + if let Err(e) = enc_proc.wait() { + error!("Validation process: {e:?}"); + } + Ok(()) } diff --git a/lib/src/utils/mod.rs b/lib/src/utils/mod.rs index af5a71a8..1a94a110 100644 --- a/lib/src/utils/mod.rs +++ b/lib/src/utils/mod.rs @@ -1,6 +1,6 @@ use std::{ ffi::OsStr, - fs::{self, metadata}, + fs::{self, metadata, File}, io::{BufRead, BufReader, Error}, net::TcpListener, path::{Path, PathBuf}, @@ -26,6 +26,7 @@ pub mod config; pub mod controller; pub mod folder; mod generator; +pub mod import; pub mod json_serializer; mod json_validate; mod logging; @@ -33,7 +34,13 @@ mod logging; #[cfg(windows)] mod windows; -pub use config::{self as playout_config, PlayoutConfig, DUMMY_LEN, IMAGE_FORMAT}; +pub use config::{ + self as playout_config, + OutputMode::{self, *}, + PlayoutConfig, + ProcessMode::{self, *}, + DUMMY_LEN, FFMPEG_IGNORE_ERRORS, IMAGE_FORMAT, +}; pub use controller::{PlayerControl, PlayoutStatus, ProcessControl, ProcessUnit::*}; pub use generator::generate_playlist; pub use json_serializer::{read_json, JsonPlaylist}; @@ -97,12 +104,12 @@ pub struct Media { } impl Media { - pub fn new(index: usize, src: String, do_probe: bool) -> Self { + pub fn new(index: usize, src: &str, do_probe: bool) -> Self { let mut duration = 0.0; let mut probe = None; - if do_probe && Path::new(&src).is_file() { - probe = Some(MediaProbe::new(&src)); + if do_probe && Path::new(src).is_file() { + probe = Some(MediaProbe::new(src)); if let Some(dur) = probe .as_ref() @@ -120,9 +127,9 @@ impl Media { out: duration, duration, category: String::new(), - source: src.clone(), + source: src.to_string(), audio: String::new(), - cmd: Some(vec!["-i".to_string(), src]), + cmd: Some(vec_strings!["-i", src]), filter: Some(vec![]), custom_filter: String::new(), probe, @@ -247,6 +254,24 @@ pub fn fps_calc(r_frame_rate: &str, default: f64) -> f64 { fps } +pub fn json_reader(path: &PathBuf) -> Result { + let f = File::options().read(true).write(false).open(&path)?; + let p = serde_json::from_reader(f)?; + + Ok(p) +} + +pub fn json_writer(path: &PathBuf, data: JsonPlaylist) -> Result<(), Error> { + let f = File::options() + .write(true) + .truncate(true) + .create(true) + .open(&path)?; + serde_json::to_writer_pretty(f, &data)?; + + Ok(()) +} + /// Covert JSON string to ffmpeg filter command. pub fn get_filter_from_json(raw_text: String) -> String { let re1 = Regex::new(r#""|}|\{"#).unwrap(); @@ -280,10 +305,10 @@ pub fn write_status(config: &PlayoutConfig, date: &str, shift: f64) { }; } -// pub fn get_timestamp() -> i64 { +// pub fn get_timestamp() -> i32 { // let local: DateTime = time_now(); -// local.timestamp_millis() as i64 +// local.timestamp_millis() as i32 // } /// Get current time in seconds. @@ -474,24 +499,16 @@ pub fn seek_and_length(node: &Media) -> Vec { let mut source_cmd = vec![]; let mut cut_audio = false; - if node.seek > 0.0 { + if node.seek > 0.5 { source_cmd.append(&mut vec_strings!["-ss", node.seek]) } - if file_extension(Path::new(&node.source)) - .unwrap_or_default() - .to_lowercase() - == "mp4" - { - source_cmd.append(&mut vec_strings!["-ignore_chapters", "1"]); - } - source_cmd.append(&mut vec_strings!["-i", node.source.clone()]); if Path::new(&node.audio).is_file() { let audio_probe = MediaProbe::new(&node.audio); - if node.seek > 0.0 { + if node.seek > 0.5 { source_cmd.append(&mut vec_strings!["-ss", node.seek]) } @@ -522,98 +539,40 @@ pub fn gen_dummy(config: &PlayoutConfig, duration: f64) -> (String, Vec) "color=c={color}:s={}x{}:d={duration}", config.processing.width, config.processing.height ); - let cmd: Vec = vec![ - "-f".to_string(), - "lavfi".to_string(), - "-i".to_string(), + let cmd: Vec = vec_strings![ + "-f", + "lavfi", + "-i", format!( "{source}:r={},format=pix_fmts=yuv420p", config.processing.fps ), - "-f".to_string(), - "lavfi".to_string(), - "-i".to_string(), - format!("anoisesrc=d={duration}:c=pink:r=48000:a=0.3"), + "-f", + "lavfi", + "-i", + format!("anoisesrc=d={duration}:c=pink:r=48000:a=0.3") ]; (source, cmd) } -/// Prepare output parameters -/// -/// seek for multiple outputs and add mapping for it -pub fn prepare_output_cmd( - prefix: Vec, - mut filter: Vec, - params: Vec, - mode: &str, -) -> Vec { - let params_len = params.len(); - let mut output_params = params.clone(); - let mut output_a_map = "[a_out1]".to_string(); - let mut output_v_map = "[v_out1]".to_string(); - let mut output_count = 1; - let mut cmd = prefix; +// fn get_output_count(cmd: &[String]) -> i32 { +// let mut count = 0; - if !filter.is_empty() { - output_params.clear(); +// if let Some(index) = cmd.iter().position(|c| c == "-var_stream_map") { +// if let Some(mapping) = cmd.get(index + 1) { +// return mapping.split(' ').count() as i32; +// }; +// }; - for (i, p) in params.iter().enumerate() { - let mut param = p.clone(); +// for (i, param) in cmd.iter().enumerate() { +// if i > 0 && !param.starts_with('-') && !cmd[i - 1].starts_with('-') { +// count += 1; +// } +// } - param = param.replace("[0:v]", "[vout1]"); - param = param.replace("[0:a]", "[aout1]"); - - if param != "-filter_complex" { - output_params.push(param.clone()); - } - - if i > 0 - && !param.starts_with('-') - && !params[i - 1].starts_with('-') - && i < params_len - 1 - { - output_count += 1; - let mut a_map = "0:a".to_string(); - let v_map = format!("[v_out{output_count}]"); - output_v_map.push_str(v_map.as_str()); - - if mode == "hls" { - a_map = format!("[a_out{output_count}]"); - } - - output_a_map.push_str(a_map.as_str()); - - let mut map = vec!["-map".to_string(), v_map, "-map".to_string(), a_map]; - - output_params.append(&mut map); - } - } - - if output_count > 1 && mode == "hls" { - filter[1].push_str(format!(";[vout1]split={output_count}{output_v_map}").as_str()); - filter[1].push_str(format!(";[aout1]asplit={output_count}{output_a_map}").as_str()); - filter.drain(2..); - cmd.append(&mut filter); - cmd.append(&mut vec_strings!["-map", "[v_out1]", "-map", "[a_out1]"]); - } else if output_count == 1 && mode == "hls" && output_params[0].contains("split") { - let out_filter = output_params.remove(0); - filter[1].push_str(format!(";{out_filter}").as_str()); - filter.drain(2..); - cmd.append(&mut filter); - } else if output_count > 1 && mode == "stream" { - filter[1].push_str(format!(",split={output_count}{output_v_map}").as_str()); - cmd.append(&mut filter); - cmd.append(&mut vec_strings!["-map", "[v_out1]", "-map", "0:a"]); - } else { - cmd.append(&mut filter); - } - } - - cmd.append(&mut output_params); - - cmd -} +// count +// } pub fn is_remote(path: &str) -> bool { Regex::new(r"^https?://.*").unwrap().is_match(path) @@ -642,7 +601,7 @@ pub fn include_file(config: PlayoutConfig, file_path: &Path) -> bool { } } - if config.out.mode.to_lowercase() == "hls" { + if config.out.mode == HLS { if let Some(ts_path) = config .out .output_cmd @@ -700,7 +659,9 @@ pub fn stderr_reader( "[{suffix}] {}", format_log_line(line, "warning") ) - } else if line.contains("[error]") || line.contains("[fatal]") { + } else if (line.contains("[error]") || line.contains("[fatal]")) + && !FFMPEG_IGNORE_ERRORS.iter().any(|i| line.contains(*i)) + { error!( "[{suffix}] {}", line.replace("[error]", "").replace("[fatal]", "") @@ -780,7 +741,7 @@ pub fn validate_ffmpeg(config: &PlayoutConfig) -> Result<(), String> { is_in_system("ffmpeg")?; is_in_system("ffprobe")?; - if config.out.mode == "desktop" { + if config.out.mode == Desktop { is_in_system("ffplay")?; } diff --git a/scripts/build_all.sh b/scripts/build.sh similarity index 72% rename from scripts/build_all.sh rename to scripts/build.sh index ff61d056..10f19040 100755 --- a/scripts/build_all.sh +++ b/scripts/build.sh @@ -1,6 +1,7 @@ #!/usr/bin/bash source $(dirname "$0")/man_create.sh +target=$1 echo "build frontend" echo @@ -14,7 +15,11 @@ mv dist ../public cd .. -targets=("x86_64-unknown-linux-musl" "aarch64-unknown-linux-gnu" "x86_64-pc-windows-gnu" "x86_64-apple-darwin" "aarch64-apple-darwin") +if [[ -n $target ]]; then + targets=($target) +else + targets=("x86_64-unknown-linux-musl" "aarch64-unknown-linux-gnu" "x86_64-pc-windows-gnu" "x86_64-apple-darwin" "aarch64-apple-darwin") +fi IFS="= " while read -r name value; do @@ -68,10 +73,14 @@ for target in "${targets[@]}"; do echo "" done -cargo deb --target=x86_64-unknown-linux-musl -p ffplayout --manifest-path=ffplayout-engine/Cargo.toml -o ffplayout_${version}_amd64.deb -cargo deb --target=aarch64-unknown-linux-gnu --variant=arm64 -p ffplayout --manifest-path=ffplayout-engine/Cargo.toml -o ffplayout_${version}_arm64.deb +if [[ -z $target ]] || [[ $target == "x86_64-unknown-linux-musl" ]]; then + cargo deb --target=x86_64-unknown-linux-musl -p ffplayout --manifest-path=ffplayout-engine/Cargo.toml -o ffplayout_${version}_amd64.deb + cd ffplayout-engine + cargo generate-rpm --target=x86_64-unknown-linux-musl -o ../ffplayout-${version}-1.x86_64.rpm -cd ffplayout-engine -cargo generate-rpm --target=x86_64-unknown-linux-musl -o ../ffplayout-${version}-1.x86_64.rpm + cd .. +fi -cd .. +if [[ -z $target ]] || [[ $target == "aarch64-unknown-linux-gnu" ]]; then + cargo deb --target=aarch64-unknown-linux-gnu --variant=arm64 -p ffplayout --manifest-path=ffplayout-engine/Cargo.toml -o ffplayout_${version}_arm64.deb +fi diff --git a/tests/Cargo.toml b/tests/Cargo.toml new file mode 100644 index 00000000..194f991c --- /dev/null +++ b/tests/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "tests" +version = "0.1.0" +edition = "2021" +publish = false + +[dev-dependencies] +ffplayout = { path = "../ffplayout-engine" } +# ffplayout-api = { path = "../ffplayout-api" } +ffplayout-lib = { path = "../lib" } + +chrono = "0.4" +crossbeam-channel = "0.5" +ffprobe = "0.3" +file-rotate = "0.7.0" +jsonrpc-http-server = "18.0" +lettre = "0.10" +log = "0.4" +notify = "4.0" +rand = "0.8" +regex = "1" +reqwest = { version = "0.11", features = ["blocking", "json"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +serde_yaml = "0.8" +shlex = "1.1" +simplelog = { version = "^0.12", features = ["paris"] } +time = { version = "0.3", features = ["formatting", "macros"] } +walkdir = "2" + +[[test]] +name = "lib_utils" +path = "src/lib_utils.rs" + +[[test]] +name = "engine_playlist" +path = "src/engine_playlist.rs" + +[[test]] +name = "engine_cmd" +path = "src/engine_cmd.rs" + diff --git a/tests/assets/ad.mp4 b/tests/assets/ad.mp4 new file mode 100644 index 00000000..d3246847 Binary files /dev/null and b/tests/assets/ad.mp4 differ diff --git a/tests/assets/audio.mp3 b/tests/assets/audio.mp3 new file mode 100644 index 00000000..26a85c8c Binary files /dev/null and b/tests/assets/audio.mp3 differ diff --git a/tests/assets/av_sync.mp4 b/tests/assets/av_sync.mp4 new file mode 100644 index 00000000..22b286a3 Binary files /dev/null and b/tests/assets/av_sync.mp4 differ diff --git a/tests/assets/dual_audio.mp4 b/tests/assets/dual_audio.mp4 new file mode 100644 index 00000000..2bbf6ed0 Binary files /dev/null and b/tests/assets/dual_audio.mp4 differ diff --git a/tests/assets/logo.png b/tests/assets/logo.png new file mode 100644 index 00000000..545bd4ac Binary files /dev/null and b/tests/assets/logo.png differ diff --git a/tests/assets/no_audio.mp4 b/tests/assets/no_audio.mp4 new file mode 100644 index 00000000..d426ec39 Binary files /dev/null and b/tests/assets/no_audio.mp4 differ diff --git a/tests/assets/playlist_full.json b/tests/assets/playlist_full.json new file mode 100755 index 00000000..17228835 --- /dev/null +++ b/tests/assets/playlist_full.json @@ -0,0 +1,22526 @@ +{ + "channel": "Channel 1", + "date": "2022-11-01", + "program": [ + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/with_audio.mp4" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + } + ] +} diff --git a/tests/assets/playlist_short.json b/tests/assets/playlist_short.json new file mode 100644 index 00000000..508a4d80 --- /dev/null +++ b/tests/assets/playlist_short.json @@ -0,0 +1,56 @@ +{ + "channel": "Channel 1", + "date": "2022-11-01", + "program": [ + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/av_sync.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/dual_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_video.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/still.jpg" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/short_audio.mp4" + }, + { + "in": 0.0, + "out": 30.0, + "duration": 30.0, + "source": "tests/assets/no_audio.mp4" + }, + { + "in": 0.0, + "out": 10.0, + "duration": 10.0, + "source": "tests/assets/still.jpg", + "audio": "tests/assets/audio.mp3" + }, + { + "in": 0.0, + "out": 25.0, + "duration": 25.0, + "source": "tests/assets/ad.mp4", + "category": "advertisement" + } + ] +} diff --git a/tests/assets/short_audio.mp4 b/tests/assets/short_audio.mp4 new file mode 100644 index 00000000..770f87bd Binary files /dev/null and b/tests/assets/short_audio.mp4 differ diff --git a/tests/assets/short_video.mp4 b/tests/assets/short_video.mp4 new file mode 100644 index 00000000..09584477 Binary files /dev/null and b/tests/assets/short_video.mp4 differ diff --git a/tests/assets/still.jpg b/tests/assets/still.jpg new file mode 100644 index 00000000..9cfdca28 Binary files /dev/null and b/tests/assets/still.jpg differ diff --git a/tests/assets/with_audio.mp4 b/tests/assets/with_audio.mp4 new file mode 100644 index 00000000..35cf6c7e Binary files /dev/null and b/tests/assets/with_audio.mp4 differ diff --git a/tests/src/engine_cmd.rs b/tests/src/engine_cmd.rs new file mode 100644 index 00000000..1e9f5170 --- /dev/null +++ b/tests/src/engine_cmd.rs @@ -0,0 +1,1080 @@ +use std::{ + fs, + sync::{Arc, Mutex}, +}; + +use ffplayout::{input::playlist::gen_source, utils::prepare_output_cmd}; +use ffplayout_lib::{ + filter::v_drawtext, + utils::{Media, OutputMode::*, PlayoutConfig}, + vec_strings, +}; + +#[test] +fn video_audio_input() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.add_logo = true; + let logo_path = fs::canonicalize("./assets/logo.png").unwrap(); + config.processing.logo = logo_path.to_string_lossy().to_string(); + + let media_obj = Media::new(0, "./assets/with_audio.mp4", true); + let media = gen_source(&config, media_obj, &Arc::new(Mutex::new(vec![]))); + + let test_filter_cmd = Some( + vec_strings![ + "-filter_complex", + format!("[0:v:0]scale=1024:576,null[v];movie={}:loop=0,setpts=N/(FRAME_RATE*TB),format=rgba,colorchannelmixer=aa=0.7[l];[v][l]overlay=W-w-12:12:shortest=1[vout0];[0:a:0]anull[aout0]", config.processing.logo), + "-map", + "[vout0]", + "-map", + "[aout0]" + ], + ); + + assert_eq!( + media.cmd, + Some(vec_strings!["-i", "./assets/with_audio.mp4"]) + ); + assert_eq!(media.filter, test_filter_cmd); +} + +#[test] +fn dual_audio_aevalsrc_input() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.audio_tracks = 2; + config.processing.add_logo = false; + + let media_obj = Media::new(0, "./assets/with_audio.mp4", true); + let media = gen_source(&config, media_obj, &Arc::new(Mutex::new(vec![]))); + + let test_filter_cmd = Some( + vec_strings![ + "-filter_complex", + "[0:v:0]scale=1024:576[vout0];[0:a:0]anull[aout0];aevalsrc=0:channel_layout=stereo:duration=30:sample_rate=48000,anull[aout1]", + "-map", + "[vout0]", + "-map", + "[aout0]", + "-map", + "[aout1]" + ], + ); + + assert_eq!( + media.cmd, + Some(vec_strings!["-i", "./assets/with_audio.mp4"]) + ); + assert_eq!(media.filter, test_filter_cmd); +} + +#[test] +fn dual_audio_input() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.audio_tracks = 2; + config.processing.add_logo = false; + + let media_obj = Media::new(0, "./assets/dual_audio.mp4", true); + let media = gen_source(&config, media_obj, &Arc::new(Mutex::new(vec![]))); + + let test_filter_cmd = Some(vec_strings![ + "-filter_complex", + "[0:v:0]scale=1024:576[vout0];[0:a:0]anull[aout0];[0:a:1]anull[aout1]", + "-map", + "[vout0]", + "-map", + "[aout0]", + "-map", + "[aout1]" + ]); + + assert_eq!( + media.cmd, + Some(vec_strings!["-i", "./assets/dual_audio.mp4"]) + ); + assert_eq!(media.filter, test_filter_cmd); +} + +#[test] +fn video_audio_stream() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.add_logo = false; + config.out.output_cmd = Some(vec_strings![ + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "flv", + "rtmp://localhost/live/stream" + ]); + + let mut enc_cmd = vec![]; + let enc_filter = vec![]; + let mut output_cmd = config.out.output_cmd.as_ref().unwrap().clone(); + + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0" + ]; + + enc_cmd.append(&mut output_cmd); + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "flv", + "rtmp://localhost/live/stream" + ]; + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn video_dual_audio_stream() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.add_logo = false; + config.processing.audio_tracks = 2; + config.out.output_cmd = Some(vec_strings![ + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40051" + ]); + + let mut enc_cmd = vec![]; + let enc_filter = vec![]; + let mut output_cmd = config.out.output_cmd.as_ref().unwrap().clone(); + + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0" + ]; + + enc_cmd.append(&mut output_cmd); + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0", + "-map", + "0:v", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40051" + ]; + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn video_dual_audio_filter_stream() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.add_logo = false; + config.processing.audio_tracks = 2; + config.text.fontfile = String::new(); + config.out.output_cmd = Some(vec_strings![ + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40051" + ]); + + let mut enc_cmd = vec![]; + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0" + ]; + + let socket = config + .text + .zmq_stream_socket + .clone() + .unwrap() + .replace(':', "\\:"); + let mut filter = "[0:v]null,".to_string(); + + filter.push_str(v_drawtext::filter_node(&config, None, &Arc::new(Mutex::new(vec![]))).as_str()); + + let enc_filter = vec!["-filter_complex".to_string(), filter]; + + let mut output_cmd = config.out.output_cmd.as_ref().unwrap().clone(); + + enc_cmd.append(&mut output_cmd); + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0", + "-filter_complex", + format!("[0:v]null,zmq=b=tcp\\\\://'{socket}',drawtext=text=''[v_out1]"), + "-map", + "[v_out1]", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40051" + ]; + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn video_audio_multi_stream() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.add_logo = false; + config.out.output_cmd = Some(vec_strings![ + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "flv", + "rtmp://localhost/live/stream", + "-s", + "512x288", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "flv", + "rtmp://localhost:1936/live/stream" + ]); + + let mut enc_cmd = vec![]; + let enc_filter = vec![]; + let mut output_cmd = config.out.output_cmd.as_ref().unwrap().clone(); + + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0" + ]; + + enc_cmd.append(&mut output_cmd); + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "flv", + "rtmp://localhost/live/stream", + "-s", + "512x288", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "flv", + "rtmp://localhost:1936/live/stream" + ]; + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn video_dual_audio_multi_stream() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.add_logo = false; + config.processing.audio_tracks = 2; + config.out.output_cmd = Some(vec_strings![ + "-map", + "0:v", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40051", + "-map", + "0:v", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-s", + "512x288", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40052" + ]); + + let mut enc_cmd = vec![]; + let enc_filter = vec![]; + let mut output_cmd = config.out.output_cmd.as_ref().unwrap().clone(); + + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0" + ]; + + enc_cmd.append(&mut output_cmd); + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0", + "-map", + "0:v", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40051", + "-map", + "0:v", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-s", + "512x288", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40052" + ]; + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn video_dual_audio_multi_filter_stream() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = Stream; + config.processing.add_logo = false; + config.processing.audio_tracks = 2; + config.text.fontfile = String::new(); + config.out.output_cmd = Some(vec_strings![ + "-map", + "0:v", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40051", + "-map", + "0:v", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-s", + "512x288", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40052" + ]); + + let mut enc_cmd = vec![]; + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0" + ]; + + let socket = config + .text + .zmq_stream_socket + .clone() + .unwrap() + .replace(':', "\\:"); + let mut filter = "[0:v]null,".to_string(); + + filter.push_str(v_drawtext::filter_node(&config, None, &Arc::new(Mutex::new(vec![]))).as_str()); + + let enc_filter = vec!["-filter_complex".to_string(), filter]; + + let mut output_cmd = config.out.output_cmd.as_ref().unwrap().clone(); + + enc_cmd.append(&mut output_cmd); + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "pipe:0", + "-filter_complex", + format!("[0:v]null,zmq=b=tcp\\\\://'{socket}',drawtext=text=''[v_out1]"), + "-map", + "[v_out1]", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40051", + "-map", + "[v_out1]", + "-map", + "0:a:0", + "-map", + "0:a:1", + "-s", + "512x288", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+global_header", + "-f", + "mpegts", + "srt://127.0.0.1:40052" + ]; + + // println!("{enc_cmd:?}"); + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn video_audio_hls() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = HLS; + config.processing.add_logo = false; + config.text.add_text = false; + config.out.output_cmd = Some(vec_strings![ + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+cgop", + "-f", + "hls", + "-hls_time", + "6", + "-hls_list_size", + "600", + "-hls_flags", + "append_list+delete_segments+omit_endlist", + "-hls_segment_filename", + "/usr/share/ffplayout/public/live/stream-%d.ts", + "/usr/share/ffplayout/public/live/stream.m3u8" + ]); + + let media_obj = Media::new(0, "./assets/with_audio.mp4", true); + let media = gen_source(&config, media_obj, &Arc::new(Mutex::new(vec![]))); + let enc_filter = media.filter.unwrap(); + + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "./assets/with_audio.mp4" + ]; + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "./assets/with_audio.mp4", + "-filter_complex", + "[0:v:0]scale=1024:576,realtime=speed=1[vout0];[0:a:0]anull[aout0]", + "-map", + "[vout0]", + "-map", + "[aout0]", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+cgop", + "-f", + "hls", + "-hls_time", + "6", + "-hls_list_size", + "600", + "-hls_flags", + "append_list+delete_segments+omit_endlist", + "-hls_segment_filename", + "/usr/share/ffplayout/public/live/stream-%d.ts", + "/usr/share/ffplayout/public/live/stream.m3u8" + ]; + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn video_multi_audio_hls() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = HLS; + config.processing.add_logo = false; + config.processing.audio_tracks = 2; + config.text.add_text = false; + config.out.output_cmd = Some(vec_strings![ + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+cgop", + "-f", + "hls", + "-hls_time", + "6", + "-hls_list_size", + "600", + "-hls_flags", + "append_list+delete_segments+omit_endlist", + "-hls_segment_filename", + "/usr/share/ffplayout/public/live/stream-%d.ts", + "/usr/share/ffplayout/public/live/stream.m3u8" + ]); + + let media_obj = Media::new(0, "./assets/dual_audio.mp4", true); + let media = gen_source(&config, media_obj, &Arc::new(Mutex::new(vec![]))); + let enc_filter = media.filter.unwrap(); + + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "./assets/dual_audio.mp4" + ]; + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "./assets/dual_audio.mp4", + "-filter_complex", + "[0:v:0]scale=1024:576,realtime=speed=1[vout0];[0:a:0]anull[aout0];[0:a:1]anull[aout1]", + "-map", + "[vout0]", + "-map", + "[aout0]", + "-map", + "[aout1]", + "-c:v", + "libx264", + "-c:a", + "aac", + "-ar", + "44100", + "-b:a", + "128k", + "-flags", + "+cgop", + "-f", + "hls", + "-hls_time", + "6", + "-hls_list_size", + "600", + "-hls_flags", + "append_list+delete_segments+omit_endlist", + "-hls_segment_filename", + "/usr/share/ffplayout/public/live/stream-%d.ts", + "/usr/share/ffplayout/public/live/stream.m3u8" + ]; + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn multi_video_audio_hls() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = HLS; + config.processing.add_logo = false; + config.text.add_text = false; + config.out.output_cmd = Some(vec_strings![ + "-filter_complex", + "[0:v]split=2[v1_out][v2];[v2]scale=w=512:h=288[v2_out];[0:a]asplit=2[a1][a2]", + "-map", + "[v1_out]", + "-map", + "[a1]", + "-c:v", + "libx264", + "-flags", + "+cgop", + "-c:a", + "aac", + "-map", + "[v2_out]", + "-map", + "[a2]", + "-c:v:1", + "libx264", + "-flags", + "+cgop", + "-c:a:1", + "aac", + "-f", + "hls", + "-hls_time", + "6", + "-hls_list_size", + "600", + "-hls_flags", + "append_list+delete_segments+omit_endlist", + "-hls_segment_filename", + "/usr/share/ffplayout/public/live/stream_%v-%d.ts", + "-master_pl_name", + "master.m3u8", + "-var_stream_map", + "v:0,a:0,name:720p v:1,a:1,name:288p", + "/usr/share/ffplayout/public/live/stream_%v.m3u8" + ]); + + let media_obj = Media::new(0, "./assets/with_audio.mp4", true); + let media = gen_source(&config, media_obj, &Arc::new(Mutex::new(vec![]))); + let enc_filter = media.filter.unwrap(); + + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "./assets/with_audio.mp4" + ]; + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "./assets/with_audio.mp4", + "-filter_complex", + "[0:v:0]scale=1024:576,realtime=speed=1[vout0];[0:a:0]anull[aout0];[vout0]split=2[v1_out][v2];[v2]scale=w=512:h=288[v2_out];[aout0]asplit=2[a1][a2]", + "-map", + "[v1_out]", + "-map", + "[a1]", + "-c:v", + "libx264", + "-flags", + "+cgop", + "-c:a", + "aac", + "-map", + "[v2_out]", + "-map", + "[a2]", + "-c:v:1", + "libx264", + "-flags", + "+cgop", + "-c:a:1", + "aac", + "-f", + "hls", + "-hls_time", + "6", + "-hls_list_size", + "600", + "-hls_flags", + "append_list+delete_segments+omit_endlist", + "-hls_segment_filename", + "/usr/share/ffplayout/public/live/stream_%v-%d.ts", + "-master_pl_name", + "master.m3u8", + "-var_stream_map", + "v:0,a:0,name:720p v:1,a:1,name:288p", + "/usr/share/ffplayout/public/live/stream_%v.m3u8" + ]; + + assert_eq!(enc_cmd, test_cmd); +} + +#[test] +fn multi_video_multi_audio_hls() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.out.mode = HLS; + config.processing.add_logo = false; + config.processing.audio_tracks = 2; + config.text.add_text = false; + config.out.output_cmd = Some(vec_strings![ + "-filter_complex", + "[0:v]split=2[v1_out][v2];[v2]scale=w=512:h=288[v2_out];[0:a:0]asplit=2[a_0_1][a_0_2];[0:a:1]asplit=2[a_1_1][a_1_2]", + "-map", + "[v1_out]", + "-map", + "[a_0_1]", + "-map", + "[a_1_1]", + "-c:v", + "libx264", + "-flags", + "+cgop", + "-c:a", + "aac", + "-map", + "[v2_out]", + "-map", + "[a_0_2]", + "-map", + "[a_1_2]", + "-c:v:1", + "libx264", + "-flags", + "+cgop", + "-c:a:1", + "aac", + "-f", + "hls", + "-hls_time", + "6", + "-hls_list_size", + "600", + "-hls_flags", + "append_list+delete_segments+omit_endlist", + "-hls_segment_filename", + "/usr/share/ffplayout/public/live/stream_%v-%d.ts", + "-master_pl_name", + "master.m3u8", + "-var_stream_map", + "v:0,a:0,a:1,name:720p v:1,a:2,a:3,name:288p", + "/usr/share/ffplayout/public/live/stream_%v.m3u8" + ]); + + let media_obj = Media::new(0, "./assets/dual_audio.mp4", true); + let media = gen_source(&config, media_obj, &Arc::new(Mutex::new(vec![]))); + let enc_filter = media.filter.unwrap(); + + let enc_prefix = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "./assets/dual_audio.mp4" + ]; + + let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, &config); + + let test_cmd = vec_strings![ + "-hide_banner", + "-nostats", + "-v", + "level+error", + "-re", + "-i", + "./assets/dual_audio.mp4", + "-filter_complex", + "[0:v:0]scale=1024:576,realtime=speed=1[vout0];[0:a:0]anull[aout0];[0:a:1]anull[aout1];[vout0]split=2[v1_out][v2];[v2]scale=w=512:h=288[v2_out];[aout0]asplit=2[a_0_1][a_0_2];[aout1]asplit=2[a_1_1][a_1_2]", + "-map", + "[v1_out]", + "-map", + "[a_0_1]", + "-map", + "[a_1_1]", + "-c:v", + "libx264", + "-flags", + "+cgop", + "-c:a", + "aac", + "-map", + "[v2_out]", + "-map", + "[a_0_2]", + "-map", + "[a_1_2]", + "-c:v:1", + "libx264", + "-flags", + "+cgop", + "-c:a:1", + "aac", + "-f", + "hls", + "-hls_time", + "6", + "-hls_list_size", + "600", + "-hls_flags", + "append_list+delete_segments+omit_endlist", + "-hls_segment_filename", + "/usr/share/ffplayout/public/live/stream_%v-%d.ts", + "-master_pl_name", + "master.m3u8", + "-var_stream_map", + "v:0,a:0,a:1,name:720p v:1,a:2,a:3,name:288p", + "/usr/share/ffplayout/public/live/stream_%v.m3u8" + ]; + + assert_eq!(enc_cmd, test_cmd); +} diff --git a/ffplayout-engine/src/tests/mod.rs b/tests/src/engine_playlist.rs similarity index 91% rename from ffplayout-engine/src/tests/mod.rs rename to tests/src/engine_playlist.rs index 76b97867..735b0da2 100644 --- a/ffplayout-engine/src/tests/mod.rs +++ b/tests/src/engine_playlist.rs @@ -3,13 +3,11 @@ use std::{ time::Duration, }; -#[cfg(test)] -use crate::output::player; -#[cfg(test)] -use ffplayout_lib::utils::*; -#[cfg(test)] use simplelog::*; +use ffplayout::output::player; +use ffplayout_lib::utils::*; + fn timed_kill(sec: u64, mut proc_ctl: ProcessControl) { sleep(Duration::from_secs(sec)); @@ -21,7 +19,7 @@ fn timed_kill(sec: u64, mut proc_ctl: ProcessControl) { fn playlist_change_at_midnight() { let mut config = PlayoutConfig::new(None); config.mail.recipient = "".into(); - config.processing.mode = "playlist".into(); + config.processing.mode = Playlist; config.playlist.day_start = "00:00:00".into(); config.playlist.length = "24:00:00".into(); config.logging.log_to_file = false; @@ -46,7 +44,7 @@ fn playlist_change_at_midnight() { fn playlist_change_at_six() { let mut config = PlayoutConfig::new(None); config.mail.recipient = "".into(); - config.processing.mode = "playlist".into(); + config.processing.mode = Playlist; config.playlist.day_start = "06:00:00".into(); config.playlist.length = "24:00:00".into(); config.logging.log_to_file = false; diff --git a/tests/src/lib_utils.rs b/tests/src/lib_utils.rs new file mode 100644 index 00000000..360e6540 --- /dev/null +++ b/tests/src/lib_utils.rs @@ -0,0 +1,52 @@ +#[cfg(test)] +use chrono::prelude::*; + +#[cfg(test)] +use ffplayout_lib::utils::*; + +#[test] +fn mock_date_time() { + let time_str = "2022-05-20T06:00:00"; + let date_obj = NaiveDateTime::parse_from_str(time_str, "%Y-%m-%dT%H:%M:%S"); + let time = Local.from_local_datetime(&date_obj.unwrap()).unwrap(); + + mock_time::set_mock_time(time_str); + + assert_eq!( + time.format("%Y-%m-%dT%H:%M:%S.2f").to_string(), + time_now().format("%Y-%m-%dT%H:%M:%S.2f").to_string() + ); +} + +#[test] +fn get_date_yesterday() { + mock_time::set_mock_time("2022-05-20T05:59:24"); + + let date = get_date(true, 21600.0, 86400.0); + + assert_eq!("2022-05-19".to_string(), date); +} + +#[test] +fn get_date_tomorrow() { + mock_time::set_mock_time("2022-05-20T23:59:30"); + + let date = get_date(false, 0.0, 86400.01); + + assert_eq!("2022-05-21".to_string(), date); +} + +#[test] +fn test_delta() { + let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string())); + config.mail.recipient = "".into(); + config.processing.mode = Playlist; + config.playlist.day_start = "00:00:00".into(); + config.playlist.length = "24:00:00".into(); + config.logging.log_to_file = false; + + mock_time::set_mock_time("2022-05-09T23:59:59"); + let (delta, _) = get_delta(&config, &86401.0); + + assert!(delta < 2.0); +}