Various scripts that I maintain

extract-m4a (new script)

matrixfurry.com 7f256cb8 9dafa890

verified
+88
+88
scripts/extract-m4a.nu
···
··· 1 + #!/usr/bin/env nu 2 + # SPDX-License-Identifier: AGPL-3.0-only 3 + # Copyright (c) 2025 Shiloh Fen <shiloh@shilohfen.com> 4 + 5 + use std log 6 + 7 + # Extract audio from a m4a file to the codec's native container 8 + def main [ 9 + path: path 10 + --rm # Remove the original file after conversion 11 + ] { 12 + let path = $path | path expand 13 + 14 + match (ls -D $path).0.type { 15 + "dir" => { 16 + let files = ls $path 17 + | get name 18 + | where $it ends-with ".m4a" 19 + 20 + let files_len = $files | length 21 + 22 + log info $"Extracting ($files_len) files." 23 + $files | par-each {|file| 24 + extract-file $file 25 + if $rm {rm $file} 26 + } 27 + log info $"Extracted ($files_len) files." 28 + } 29 + "file" => { 30 + extract-file $path 31 + if $rm {rm $path} 32 + } 33 + _ => (error make { 34 + msg: "Invalid path" 35 + label: { 36 + text: $"Invalid path: ($path)" 37 + span: (metadata $path).span 38 + } 39 + }) 40 + } 41 + } 42 + 43 + def extract-file [file: path] { 44 + let file = $file | path expand 45 + let parsed_path = $file | path parse 46 + 47 + log info $"Extracting `($file)`" 48 + 49 + if $parsed_path.extension != "m4a" { 50 + error make { 51 + msg: "Format not supported" 52 + label: { 53 + text: $"Unsupported format: \"($parsed_path.extension)\"" 54 + span: (metadata $file).span 55 + } 56 + help: "This tool currently only supports M4A." 57 + } 58 + } 59 + 60 + let codec = ffprobe -v quiet -select_streams a -show_entries stream=codec_name -of csv=p=0 $file | split row "," 61 + # Args: 62 + # -v quiet -> Only print result 63 + # -select_streams a -> Select only audio streams, in case there is album artwork or a video embedded as a stream 64 + # -show_entries stream=codec_name -> Get codec 65 + # -of csv=p=0 -> print comma-seperated list with no headers 66 + 67 + if ($codec | length) > 1 { 68 + error make { 69 + msg: "Too many audio streams" 70 + label: { 71 + text: $"Contains more than 1 audio stream: ($codec | length)" 72 + span: (metadata $file).span 73 + } 74 + help: "This tool can currently only handle a single audio stream" 75 + } 76 + } 77 + 78 + let codec = $codec.0 79 + 80 + let output: path = $"($parsed_path.parent)/($parsed_path.stem).($codec)" 81 + 82 + ffmpeg -v quiet -i $file -c:a copy -vn $output 83 + # Args: 84 + # -c:a copy -> Copy codec 85 + # -vn -> No video 86 + 87 + log info $"Extracted `($file)` to `($output)`" 88 + }