diff --git a/Makefile b/Makefile index 7b7f969..b64c7e3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SHELL:=/nix/store/zicq9x6aznw7x202564p8iy0rm04py6l-nushell-0.89.0/bin/nu +SHELL:=/nix/store/kx4ic1nmgsfh3qhr74vxq7g97pal7mn4-nushell-0.108.0/bin/nu all: README.md diff --git a/README.md b/README.md index 79f2823..111450f 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Utility commands for working with ffmpeg in nushell. The `ffmpeg` and `ffprobe` commands are required to be installed and available in your path; they are not installed for you. -Currently only nushell version 0.89.0 is supported. +Currently only nushell version 0.108.0 is supported. After that, clone this repository and add the following code to your scripts, or to your `config.nu` file: @@ -32,8 +32,9 @@ use /filters * ### Commands -| name | usage | +| name | description | | --------------------- | ---------------------------------------------------------------- | +| ffprobe banner | Print a banner for Nushell with information about the project | | ffprobe | Run ffprobe on a list of files and return the output as a table. | | ffprobe dimensions | Get the dimensions of a video stream | | ffprobe streams | Retrieve all the streams from a list of ffprobe outputs | @@ -45,16 +46,17 @@ use /filters * ### Supported Filters -| name | usage | +| name | description | | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| banner | Print a banner for Nushell with information about the project | | crop | Crop the input video to given dimensions. | | format | Convert the input video to one of the specified pixel formats. Libavfilter will try to pick one that is suitable as input to the next filter. | | fps | Convert the video to specified constant frame rate by duplicating or dropping frames as necessary. | -| loop | loop video frames | | overlay | Overlay one video on top of another. | | settb | Set the timebase to use for the output frames timestamps. It is mainly useful for testing timebase configuration. | | split | | | vflip | Flip the input video vertically. | +| vloop | loop video frames Same as the `loop` filter in ffmpeg, but had to be renamed due to collisions with the [nushell builtin](https://www.nushell.sh/commands/docs/loop.html) | | xfade | Apply cross fade from one input video stream to another input video stream. The cross fade is applied for specified duration. Both inputs must be constant frame-rate and have the same resolution, pixel format, frame rate and timebase. | @@ -63,54 +65,109 @@ use /filters * ```nu # Return a table from ffprobe > ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 -╭───┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────╮ -│ # │ streams │ format │ -├───┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────┤ -│ 0 │ ╭───┬────────────┬───────────────────────────────────────────┬─────────┬────────────┬──────────────────┬────────────┬───────┬────────┬─────────────┬──────────────┬─────────────────┬────────────┬──────────────┬─────╮ │ {record 11 │ -│ │ │ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_string │ codec_tag │ width │ height │ coded_width │ coded_height │ closed_captions │ film_grain │ has_b_frames │ ... │ │ fields} │ -│ │ ├───┼────────────┼───────────────────────────────────────────┼─────────┼────────────┼──────────────────┼────────────┼───────┼────────┼─────────────┼──────────────┼─────────────────┼────────────┼──────────────┼─────┤ │ │ -│ │ │ 0 │ h264 │ H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 │ Main │ video │ avc1 │ 0x31637661 │ 1280 │ 720 │ 1280 │ 720 │ 0 │ 0 │ 0 │ ... │ │ │ -│ │ │ 1 │ aac │ AAC (Advanced Audio Coding) │ LC │ audio │ mp4a │ 0x6134706d │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ... │ │ │ -│ │ ╰───┴────────────┴───────────────────────────────────────────┴─────────┴────────────┴──────────────────┴────────────┴───────┴────────┴─────────────┴──────────────┴─────────────────┴────────────┴──────────────┴─────╯ │ │ -╰───┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────╯ +╭───┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬───╮ +│ # │ streams │ f │ +│ │ │ o │ +│ │ │ r │ +│ │ │ m │ +│ │ │ a │ +│ │ │ t │ +├───┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───┤ +│ 0 │ ╭───┬────────────┬───────────────────────────────────────────┬─────────┬────────────┬───────────────┬─────╮ │ { │ +│ │ │ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_str │ ... │ │ r │ +│ │ │ │ │ │ │ │ ing │ │ │ e │ +│ │ ├───┼────────────┼───────────────────────────────────────────┼─────────┼────────────┼───────────────┼─────┤ │ c │ +│ │ │ 0 │ h264 │ H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 │ Main │ video │ avc1 │ ... │ │ o │ +│ │ │ 1 │ aac │ AAC (Advanced Audio Coding) │ LC │ audio │ mp4a │ ... │ │ r │ +│ │ ╰───┴────────────┴───────────────────────────────────────────┴─────────┴────────────┴───────────────┴─────╯ │ d │ +│ │ │ │ +│ │ │ 1 │ +│ │ │ 2 │ +│ │ │ │ +│ │ │ f │ +│ │ │ i │ +│ │ │ e │ +│ │ │ l │ +│ │ │ d │ +│ │ │ s │ +│ │ │ } │ +╰───┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───╯ ``` ```nu # Use ffprobe on mutliple files at once > ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 https://sample-videos.com/video321/mkv/720/big_buck_bunny_720p_1mb.mkv -╭───┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────╮ -│ # │ streams │ format │ -├───┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────┤ -│ 0 │ ╭───┬────────────┬───────────────────────────────────────────┬─────────┬────────────┬──────────────────┬────────────┬───────┬────────┬─────────────┬──────────────┬─────────────────┬────────────┬──────────────┬─────╮ │ {record 11 │ -│ │ │ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_string │ codec_tag │ width │ height │ coded_width │ coded_height │ closed_captions │ film_grain │ has_b_frames │ ... │ │ fields} │ -│ │ ├───┼────────────┼───────────────────────────────────────────┼─────────┼────────────┼──────────────────┼────────────┼───────┼────────┼─────────────┼──────────────┼─────────────────┼────────────┼──────────────┼─────┤ │ │ -│ │ │ 0 │ h264 │ H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 │ Main │ video │ avc1 │ 0x31637661 │ 1280 │ 720 │ 1280 │ 720 │ 0 │ 0 │ 0 │ ... │ │ │ -│ │ │ 1 │ aac │ AAC (Advanced Audio Coding) │ LC │ audio │ mp4a │ 0x6134706d │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ... │ │ │ -│ │ ╰───┴────────────┴───────────────────────────────────────────┴─────────┴────────────┴──────────────────┴────────────┴───────┴────────┴─────────────┴──────────────┴─────────────────┴────────────┴──────────────┴─────╯ │ │ -│ 1 │ ╭───┬────────────┬─────────────────────────────┬────────────────┬────────────┬──────────────────┬───────────┬───────┬────────┬─────────────┬──────────────┬─────────────────┬────────────┬──────────────┬─────╮ │ {record 10 │ -│ │ │ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_string │ codec_tag │ width │ height │ coded_width │ coded_height │ closed_captions │ film_grain │ has_b_frames │ ... │ │ fields} │ -│ │ ├───┼────────────┼─────────────────────────────┼────────────────┼────────────┼──────────────────┼───────────┼───────┼────────┼─────────────┼──────────────┼─────────────────┼────────────┼──────────────┼─────┤ │ │ -│ │ │ 0 │ mpeg4 │ MPEG-4 part 2 │ Simple Profile │ video │ [0][0][0][0] │ 0x0000 │ 1280 │ 720 │ 1280 │ 720 │ 0 │ 0 │ 0 │ ... │ │ │ -│ │ │ 1 │ aac │ AAC (Advanced Audio Coding) │ LC │ audio │ [0][0][0][0] │ 0x0000 │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ❎ │ ... │ │ │ -│ │ ╰───┴────────────┴─────────────────────────────┴────────────────┴────────────┴──────────────────┴───────────┴───────┴────────┴─────────────┴──────────────┴─────────────────┴────────────┴──────────────┴─────╯ │ │ -╰───┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────╯ +╭───┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────┬───╮ +│ # │ streams │ f │ +│ │ │ o │ +│ │ │ r │ +│ │ │ m │ +│ │ │ a │ +│ │ │ t │ +├───┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────┼───┤ +│ 0 │ ╭───┬────────────┬───────────────────────────────────────────┬─────────┬────────────┬───────────────┬─────╮ │ { │ +│ │ │ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_str │ ... │ │ r │ +│ │ │ │ │ │ │ │ ing │ │ │ e │ +│ │ ├───┼────────────┼───────────────────────────────────────────┼─────────┼────────────┼───────────────┼─────┤ │ c │ +│ │ │ 0 │ h264 │ H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 │ Main │ video │ avc1 │ ... │ │ o │ +│ │ │ 1 │ aac │ AAC (Advanced Audio Coding) │ LC │ audio │ mp4a │ ... │ │ r │ +│ │ ╰───┴────────────┴───────────────────────────────────────────┴─────────┴────────────┴───────────────┴─────╯ │ d │ +│ │ │ │ +│ │ │ 1 │ +│ │ │ 2 │ +│ │ │ │ +│ │ │ f │ +│ │ │ i │ +│ │ │ e │ +│ │ │ l │ +│ │ │ d │ +│ │ │ s │ +│ │ │ } │ +│ 1 │ ╭───┬────────────┬─────────────────────────────┬────────────────┬────────────┬──────────────────┬───┬─────╮ │ { │ +│ │ │ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_string │ c │ ... │ │ r │ +│ │ │ │ │ │ │ │ │ o │ │ │ e │ +│ │ │ │ │ │ │ │ │ d │ │ │ c │ +│ │ │ │ │ │ │ │ │ e │ │ │ o │ +│ │ │ │ │ │ │ │ │ c │ │ │ r │ +│ │ │ │ │ │ │ │ │ _ │ │ │ d │ +│ │ │ │ │ │ │ │ │ t │ │ │ │ +│ │ │ │ │ │ │ │ │ a │ │ │ 1 │ +│ │ │ │ │ │ │ │ │ g │ │ │ 1 │ +│ │ ├───┼────────────┼─────────────────────────────┼────────────────┼────────────┼──────────────────┼───┼─────┤ │ │ +│ │ │ 0 │ mpeg4 │ MPEG-4 part 2 │ Simple Profile │ video │ [0][0][0][0] │ 0 │ ... │ │ f │ +│ │ │ │ │ │ │ │ │ x │ │ │ i │ +│ │ │ │ │ │ │ │ │ 0 │ │ │ e │ +│ │ │ │ │ │ │ │ │ 0 │ │ │ l │ +│ │ │ │ │ │ │ │ │ 0 │ │ │ d │ +│ │ │ │ │ │ │ │ │ 0 │ │ │ s │ +│ │ │ 1 │ aac │ AAC (Advanced Audio Coding) │ LC │ audio │ [0][0][0][0] │ 0 │ ... │ │ } │ +│ │ │ │ │ │ │ │ │ x │ │ │ │ +│ │ │ │ │ │ │ │ │ 0 │ │ │ │ +│ │ │ │ │ │ │ │ │ 0 │ │ │ │ +│ │ │ │ │ │ │ │ │ 0 │ │ │ │ +│ │ │ │ │ │ │ │ │ 0 │ │ │ │ +│ │ ╰───┴────────────┴─────────────────────────────┴────────────────┴────────────┴──────────────────┴───┴─────╯ │ │ +╰───┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────┴───╯ ``` ```nu # Extract the video streams from a video > ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 | streams video -╭────┬────────────┬───────────────────────────────────────────┬─────────┬────────────┬──────────────────┬────────────┬───────┬────────┬─────────────┬──────────────┬─────────────────┬────────────┬──────────────┬─────────────────────┬─────╮ -│ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_string │ codec_tag │ width │ height │ coded_width │ coded_height │ closed_captions │ film_grain │ has_b_frames │ sample_aspect_ratio │ ... │ -├────┼────────────┼───────────────────────────────────────────┼─────────┼────────────┼──────────────────┼────────────┼───────┼────────┼─────────────┼──────────────┼─────────────────┼────────────┼──────────────┼─────────────────────┼─────┤ -│ 0 │ h264 │ H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 │ Main │ video │ avc1 │ 0x31637661 │ 1280 │ 720 │ 1280 │ 720 │ 0 │ 0 │ 0 │ 1:1 │ ... │ -╰────┴────────────┴───────────────────────────────────────────┴─────────┴────────────┴──────────────────┴────────────┴───────┴────────┴─────────────┴──────────────┴─────────────────┴────────────┴──────────────┴─────────────────────┴─────╯ +╭───┬────────────┬───────────────────────────────────────────┬─────────┬────────────┬──────────────────┬────────┬─────╮ +│ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_string │ codec_ │ ... │ +│ │ │ │ │ │ │ tag │ │ +├───┼────────────┼───────────────────────────────────────────┼─────────┼────────────┼──────────────────┼────────┼─────┤ +│ 0 │ h264 │ H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 │ Main │ video │ avc1 │ 0x3163 │ ... │ +│ │ │ │ │ │ │ 7661 │ │ +╰───┴────────────┴───────────────────────────────────────────┴─────────┴────────────┴──────────────────┴────────┴─────╯ # Extract the audio streams from a video > ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 | streams audio -╭───┬────────────┬─────────────────────────────┬─────────┬────────────┬──────────────────┬────────────┬────────────┬─────────────┬──────────┬────────────────┬─────────────────┬─────────────────┬─────┬──────────────┬────────────────┬─────╮ -│ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_string │ codec_tag │ sample_fmt │ sample_rate │ channels │ channel_layout │ bits_per_sample │ initial_padding │ id │ r_frame_rate │ avg_frame_rate │ ... │ -├───┼────────────┼─────────────────────────────┼─────────┼────────────┼──────────────────┼────────────┼────────────┼─────────────┼──────────┼────────────────┼─────────────────┼─────────────────┼─────┼──────────────┼────────────────┼─────┤ -│ 1 │ aac │ AAC (Advanced Audio Coding) │ LC │ audio │ mp4a │ 0x6134706d │ fltp │ 48000 │ 6 │ 5.1 │ 0 │ 0 │ 0x2 │ 0/0 │ 0/0 │ ... │ -╰───┴────────────┴─────────────────────────────┴─────────┴────────────┴──────────────────┴────────────┴────────────┴─────────────┴──────────┴────────────────┴─────────────────┴─────────────────┴─────┴──────────────┴────────────────┴─────╯ +╭───┬────────────┬─────────────────────────────┬─────────┬────────────┬──────────────────┬────────────┬─────────┬─────╮ +│ # │ codec_name │ codec_long_name │ profile │ codec_type │ codec_tag_string │ codec_tag │ sample_ │ ... │ +│ │ │ │ │ │ │ │ fmt │ │ +├───┼────────────┼─────────────────────────────┼─────────┼────────────┼──────────────────┼────────────┼─────────┼─────┤ +│ 1 │ aac │ AAC (Advanced Audio Coding) │ LC │ audio │ mp4a │ 0x6134706d │ fltp │ ... │ +╰───┴────────────┴─────────────────────────────┴─────────┴────────────┴──────────────────┴────────────┴─────────┴─────╯ ``` ```nu diff --git a/examples/dimensions.nu b/examples/dimensions.nu index a98c578..02e317e 100755 --- a/examples/dimensions.nu +++ b/examples/dimensions.nu @@ -3,8 +3,12 @@ use ../ffprobe ["main" "dimensions" "streams video"]; def main [] { - echo "# Extract the dimensions of a video stream" - echo "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 | streams video | first | dimensions" - ffprobe $'($env.FILE_PWD)/videos/sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4' - | streams video | first | dimensions + print "# Extract the dimensions of a video stream" + print "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 | streams video | first | dimensions" + ( + ffprobe $'($env.FILE_PWD)/videos/sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4' + | streams video + | first + | dimensions + ) } diff --git a/examples/ffprobe-multiple-files.nu b/examples/ffprobe-multiple-files.nu index 9288444..8dbbe2f 100755 --- a/examples/ffprobe-multiple-files.nu +++ b/examples/ffprobe-multiple-files.nu @@ -3,8 +3,8 @@ use ../ffprobe; def main [] { - echo "# Use ffprobe on mutliple files at once" - echo "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 https://sample-videos.com/video321/mkv/720/big_buck_bunny_720p_1mb.mkv" + print "# Use ffprobe on mutliple files at once" + print "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 https://sample-videos.com/video321/mkv/720/big_buck_bunny_720p_1mb.mkv" ( ffprobe $'($env.FILE_PWD)/videos/sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4' diff --git a/examples/ffprobe.nu b/examples/ffprobe.nu index f497ec1..99dc07d 100755 --- a/examples/ffprobe.nu +++ b/examples/ffprobe.nu @@ -3,7 +3,7 @@ use ../ffprobe; def main [] { - echo "# Return a table from ffprobe" - echo "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4" + print "# Return a table from ffprobe" + print "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4" ffprobe $'($env.FILE_PWD)/videos/sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4' } diff --git a/examples/streams-audio.nu b/examples/streams-audio.nu index 2e2aaaa..0fd8501 100755 --- a/examples/streams-audio.nu +++ b/examples/streams-audio.nu @@ -3,8 +3,8 @@ use ../ffprobe ["main" "streams audio"]; def main [] { - echo "# Extract the audio streams from a video" - echo "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 | streams audio" + print "# Extract the audio streams from a video" + print "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 | streams audio" ffprobe $'($env.FILE_PWD)/videos/sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4' | streams audio } diff --git a/examples/streams-video.nu b/examples/streams-video.nu index cdaa3a7..d0b46f7 100755 --- a/examples/streams-video.nu +++ b/examples/streams-video.nu @@ -3,8 +3,8 @@ use ../ffprobe ["main" "streams video"]; def main [] { - echo "# Extract the video streams from a video" - echo "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 | streams video" + print "# Extract the video streams from a video" + print "> ffprobe https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4 | streams video" ffprobe $'($env.FILE_PWD)/videos/sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4' | streams video } diff --git a/ffmpeg.nu b/ffmpeg.nu index 5acb7c1..0748da1 100644 --- a/ffmpeg.nu +++ b/ffmpeg.nu @@ -82,8 +82,8 @@ export def "parse filter" [ ]: string -> table> { parse --regex '^\s*(?:\[(?[^\s]+)\]\s*)?(?[^=\s\[]+)\s*(?:=(?[^\[\s,;]*)\s*)?(?:\[(?[^\s,;]+)\])?' | first | update params { parse --regex `(?:(?[^=]+)=)?(?[^:]+):?` - } | update input { split row '][' | filter { is-not-empty } - } | update output { split row '][' | filter { is-not-empty } } + } | update input { split row '][' | where { is-not-empty } + } | update output { split row '][' | where { is-not-empty } } } # TODO: Remove export @@ -95,7 +95,7 @@ def "filterchain to-string" []: table -> string { $in | each { filter to-string }| str join ',' } -def "filter to-string" []: record name: string params: table output: list> -> string { +def "filter to-string" []: record name: string params: table output: list> -> string { $in | update input { str join '][' } | update output { @@ -176,7 +176,3 @@ export def append-complex-filter [ (complex-filter --input $input --output $output $name $params) ] } - -def is-not-empty []: any -> bool { - is-empty | not $in -} diff --git a/ffmpeg_test.nu b/ffmpeg_test.nu index c334b85..e46551b 100644 --- a/ffmpeg_test.nu +++ b/ffmpeg_test.nu @@ -100,7 +100,7 @@ def boolean_params_are_converted_to_1_or_0 [] { #[test] def without_filterchain_chains_are_concated [] { - let got = (cmd ['INPUT'] ['OUTPUT'] | fps 25 | loop 2 1); + let got = (cmd ['INPUT'] ['OUTPUT'] | fps 25 | vloop 2 1); assert equal $got { input: ['INPUT'] @@ -140,7 +140,7 @@ def without_filterchain_chains_are_concated [] { } #[test] def filterchain_concats_filters [] { - let got = (cmd ['INPUT'] ['OUTPUT'] | filterchain { fps 25 -i ['in'] | loop 2 1 -o ['out']}); + let got = (cmd ['INPUT'] ['OUTPUT'] | filterchain { fps 25 -i ['in'] | vloop 2 1 -o ['out']}); assert equal $got { input: ['INPUT'] @@ -179,7 +179,7 @@ def filterchain_concats_filters [] { #[test] def filterchain_appends_current_filter [] { - let got = (cmd ['INPUT'] ['OUTPUT'] | fps 12 | filterchain { fps 25 -i ['in'] | loop 2 1 -o ['out']}); + let got = (cmd ['INPUT'] ['OUTPUT'] | fps 12 | filterchain { fps 25 -i ['in'] | vloop 2 1 -o ['out']}); assert equal $got { input: ['INPUT'] diff --git a/ffprobe b/ffprobe index 7e0435b..93e97cc 100755 --- a/ffprobe +++ b/ffprobe @@ -31,6 +31,6 @@ export def "streams audio" []: table -> table { } # Get the dimensions of a video stream -export def "dimensions" []: table -> record { +export def "dimensions" []: record -> record { $in | select width height } diff --git a/filters.nu b/filters.nu index ff2cdc4..f3f1ed1 100755 --- a/filters.nu +++ b/filters.nu @@ -5,9 +5,11 @@ use std [assert]; use ./ffmpeg.nu ["append-complex-filter"] # loop video frames -export def loop [ - --input (-i): list: = [] - --output (-o): list: = [] +# Same as the `loop` filter in ffmpeg, but +# had to be renamed due to collisions with the [nushell builtin](https://www.nushell.sh/commands/docs/loop.html) +export def "vloop" [ + --input (-i): list = [] + --output (-o): list = [] loop: int # Set the number of loops. Setting this value to -1 will result in infinite loops. Default is 0. size: int # Set maximal size in number of frames. Default is 0. --start (-s): int # Set first frame of loop. Default is 0. @@ -23,8 +25,8 @@ export def loop [ # Convert the video to specified constant frame rate by duplicating or dropping frames as necessary. export def fps [ - --input (-i): list: = [] - --output (-o): list: = [] + --input (-i): list = [] + --output (-o): list = [] --start-time (-s) # Assume the first PTS should be the given value, in seconds. # This allows for padding/trimming at the start of stream. By default, no assumption is made about the first frame’s expected PTS, so no padding or trimming is done. For example, this could be set to 0 to pad the beginning with duplicates of the first frame if a video stream starts after the audio stream or to trim any frames with a negative PTS. --round (-r): string@fps-round # Timestamp (PTS) rounding method. use completion to view available options. @@ -63,8 +65,8 @@ def fps-fps [] { # Set the timebase to use for the output frames timestamps. It is mainly useful for testing timebase configuration. export def settb [ - --input (-i): list: = [] - --output (-o): list: = [] + --input (-i): list = [] + --output (-o): list = [] timebase # The value for tb is an arithmetic expression representing a rational. The expression can contain the constants "AVTB" (the default timebase), "intb" (the input timebase) and "sr" (the sample rate, audio only). Default value is "intb". ] { (append-complex-filter settb {expr: $timebase} -i $input -o $output) @@ -81,8 +83,8 @@ def "list to-pipe-separated-string" []: list -> string { # Convert the input video to one of the specified pixel formats. Libavfilter will try to pick one that is suitable as input to the next filter. export def format [ - --input (-i): list: = [] - --output (-o): list: = [] + --input (-i): list = [] + --output (-o): list = [] --pix-fmts (-p): list # A list of pixel format names --color-spaces (-c): list # A list of color space names --color-ranges (-r): list # A list of color range names @@ -208,7 +210,7 @@ def xfade-expressions [context: string] { } export def split [ - --input (-i): list: = [] + --input (-i): list = [] output: list ] { let cmd = $in; diff --git a/filters_test.nu b/filters_test.nu index c8d65d5..d5a1874 100644 --- a/filters_test.nu +++ b/filters_test.nu @@ -2,18 +2,19 @@ use std [assert]; -use ./filters.nu [complex-filter loop "parse filter"]; +use ./ffmpeg.nu [complex-filter "parse filter"]; +use ./filters.nu [vloop]; # #[test] def loop_has_defaults [] { - let got = (loop 10 1); + let got = (vloop 10 1); let want = (complex-filter 'loop' { loop: 10 size: 1 }); assert equal $got $want; } # #[test] def setting_time_sets_start_to-1 [] { - let got = (loop 10 1 -t 0.5); + let got = (vloop 10 1 -t 0.5); let want = (complex-filter 'loop' { loop: 10 size: 1 diff --git a/flake.lock b/flake.lock index 5dd1e12..c5720d7 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1712163089, - "narHash": "sha256-Um+8kTIrC19vD4/lUCN9/cU9kcOsD1O1m+axJqQPyMM=", + "lastModified": 1766902085, + "narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "fd281bd6b7d3e32ddfa399853946f782553163b5", + "rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index a264504..83ad800 100644 --- a/flake.nix +++ b/flake.nix @@ -20,7 +20,7 @@ hugo yarn - nushellFull + nushell ]; }; }; diff --git a/get_ffprobe_commands_table b/get_ffprobe_commands_table index bfb83c3..8c47934 100755 --- a/get_ffprobe_commands_table +++ b/get_ffprobe_commands_table @@ -7,9 +7,9 @@ def main [] { ( help commands | where command_type == "custom" and name !~ "p(rompt|wd)" - | select name usage + | select name description | update name { if $in == 'main' { 'ffprobe' } else { $'ffprobe ($in)' } } - | filter { not ($in.name == 'ffprobe' and ($in.usage | is-empty)) } + | where { not ($in.name == 'ffprobe' and ($in.description | is-empty)) } | to md -p ) } diff --git a/get_filter_support_table b/get_filter_support_table index 237995b..d551840 100755 --- a/get_filter_support_table +++ b/get_filter_support_table @@ -7,8 +7,8 @@ def main [] { ( help commands | where command_type == "custom" and name !~ "p(rompt|wd)|^main$" - | select name usage - | update usage { + | select name description + | update description { str replace -a "\n" " " } | to md -p