mediasnacks 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediasnacks",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Utilities for preparing videos, images, and audio for the web",
5
5
  "license": "MIT",
6
6
  "author": "Eric Fortis",
@@ -1,13 +1,13 @@
1
1
  import { join } from 'node:path'
2
2
  import { tmpdir } from 'node:os'
3
3
  import { equal, deepEqual } from 'node:assert/strict'
4
- import { mkdtemp, writeFile, rm } from 'node:fs/promises'
4
+ import { mkdtemp, writeFile, rmdir } from 'node:fs/promises'
5
5
  import { test, describe, before, after } from 'node:test'
6
6
 
7
7
  import { parseOptions } from './parseOptions.js'
8
8
 
9
9
 
10
- describe('parseArgsWithGlobs', () => {
10
+ describe('parseOptions', () => {
11
11
  let testDir
12
12
  let inTmpDir = f => join(testDir, f)
13
13
  const testFiles = ['file1.png', 'file2.png', 'file3.png']
@@ -18,7 +18,7 @@ describe('parseArgsWithGlobs', () => {
18
18
  await writeFile(inTmpDir(file), '')
19
19
  })
20
20
 
21
- after(() => rm(testDir))
21
+ after(() => rmdir(testDir, { recursive: true }))
22
22
 
23
23
  test('parses args and globs files', async () => {
24
24
  const { values, files } = await parseOptions({
package/src/vsplit.sh CHANGED
@@ -1,46 +1,50 @@
1
1
  #!/bin/zsh
2
2
 
3
3
  if [ "$#" -lt 2 ]; then
4
- cat << EOF
4
+ cat << EOF
5
5
  Usage:
6
6
  $(basename $0) <split-time-1> [split-time-2 ...] <video-file>
7
7
 
8
8
  Examples:
9
- $(basename $0) 123.45 input.mp4
9
+ $(basename $0) 123.45 video.mp4
10
10
  $(basename $0) 60 120 180 video.mov
11
- $(basename $0) 00:01:00 00:02:00 00:03:00 input.mkv
11
+ $(basename $0) 00:01:00 00:02:00 00:03:00 video.mkv
12
12
  EOF
13
- exit 1
13
+ exit 1
14
14
  fi
15
15
 
16
16
  VIDEO="${@[-1]}"
17
17
  SPLITS=("${@[1,-2]}")
18
18
 
19
19
  if [ ! -f "$VIDEO" ]; then
20
- echo "Error: file not found: $VIDEO"
21
- exit 1
20
+ echo "Error: file not found: $VIDEO"
21
+ exit 1
22
22
  fi
23
23
 
24
- BASENAME=$(basename "$VIDEO")
25
24
  DIRNAME=$(dirname "$VIDEO")
25
+ BASENAME=$(basename "$VIDEO")
26
26
  EXT="${BASENAME##*.}"
27
27
  NAME="${BASENAME%.*}"
28
28
 
29
- SEGMENT_COUNT=$((${#SPLITS[@]} + 1))
30
-
31
- for (( i=1; i<=$SEGMENT_COUNT; i++ )); do
32
- OUTFILE="$DIRNAME/${NAME}_${i}.$EXT"
33
-
34
- if [ $i -eq 1 ]; then
35
- # First segment: from start to first split
36
- ffmpeg -v error -y -i "$VIDEO" -t "${SPLITS[1]}" -c copy "$OUTFILE"
37
- elif [ $i -eq $SEGMENT_COUNT ]; then
38
- # Last segment: from last split to end
39
- ffmpeg -v error -y -ss "${SPLITS[-1]}" -i "$VIDEO" -c copy "$OUTFILE"
40
- else
41
- # Middle segments: from split[i-1] to split[i]
42
- PREV_SPLIT="${SPLITS[$((i-1))]}"
43
- CURR_SPLIT="${SPLITS[$i]}"
44
- ffmpeg -v error -y -ss "$PREV_SPLIT" -to "$CURR_SPLIT" -i "$VIDEO" -c copy "$OUTFILE"
45
- fi
29
+ N_CLIPS=$((${#SPLITS[@]} + 1))
30
+
31
+ for (( i=1; i<=$N_CLIPS; i++ )); do
32
+ outfile="$DIRNAME/${NAME}_${i}.$EXT"
33
+
34
+ if [ $i -eq 1 ]; then # First clip: [start, first_split]
35
+ ffmpeg -v error -y -i "$VIDEO" \
36
+ -t "${SPLITS[1]}" \
37
+ -c copy "$outfile"
38
+
39
+ elif [ $i -eq $N_CLIPS ]; then # Last clip: [last_split, end]
40
+ ffmpeg -v error -y -i "$VIDEO" \
41
+ -ss "${SPLITS[-1]}" \
42
+ -c copy "$outfile"
43
+
44
+ else # Middle clip: [split[i-1], split[i]]
45
+ ffmpeg -v error -y -i "$VIDEO" \
46
+ -ss "${SPLITS[$((i-1))]}" \
47
+ -to "${SPLITS[$i]}" \
48
+ -c copy "$outfile"
49
+ fi
46
50
  done
package/src/vtrim.sh CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/zsh
2
2
 
3
3
  if [ "$#" -ne 3 ]; then
4
- cat << EOF
4
+ cat << EOF
5
5
  Usage:
6
6
  $(basename $0) <start-time> <end-time> <video-file>
7
7
 
@@ -10,7 +10,7 @@ Examples:
10
10
  $(basename $0) 00:00:10 00:00:30 input.mkv
11
11
  $(basename $0) 1:23.5 2:45.0 video.mov
12
12
  EOF
13
- exit 1
13
+ exit 1
14
14
  fi
15
15
 
16
16
  START="$1"
@@ -18,8 +18,8 @@ END="$2"
18
18
  VIDEO="$3"
19
19
 
20
20
  if [ ! -f "$VIDEO" ]; then
21
- echo "Error: file not found: $VIDEO"
22
- exit 1
21
+ echo "Error: file not found: $VIDEO"
22
+ exit 1
23
23
  fi
24
24
 
25
25
  BASENAME=$(basename "$VIDEO")
@@ -27,6 +27,9 @@ DIRNAME=$(dirname "$VIDEO")
27
27
  EXT="${BASENAME##*.}"
28
28
  NAME="${BASENAME%.*}"
29
29
 
30
- OUTFILE="$DIRNAME/${NAME}.trim.$EXT"
30
+ outfile="$DIRNAME/${NAME}.trim.$EXT"
31
31
 
32
- ffmpeg -v error -y -ss "$START" -to "$END" -i "$VIDEO" -c copy "$OUTFILE"
32
+ ffmpeg -v error -y -i "$VIDEO" \
33
+ -ss "$START" \
34
+ -to "$END" \
35
+ -c copy "$outfile"
@@ -3,20 +3,13 @@ import { test } from 'node:test'
3
3
  import { equal } from 'node:assert/strict'
4
4
  import { tmpdir } from 'node:os'
5
5
  import { execSync } from 'node:child_process'
6
- import { createHash } from 'node:crypto'
7
- import { mkdtempSync, readFileSync } from 'node:fs'
6
+ import { mkdtempSync } from 'node:fs'
7
+
8
+ import { sha1 } from './utils.js'
8
9
 
9
- function sha1(filePath) {
10
- return createHash('sha1').update(readFileSync(filePath)).digest('hex')
11
- }
12
10
 
13
11
  test('PNG to AVIF', () => {
14
12
  const tmp = mkdtempSync(join(tmpdir(), 'avif-test-'))
15
-
16
- execSync(`src/cli.js avif --output-dir ${tmp} tests/fixtures/lenna.png`, {
17
- cwd: process.cwd(),
18
- stdio: 'inherit'
19
- })
20
-
13
+ execSync(`src/cli.js avif --output-dir ${tmp} tests/fixtures/lenna.png` )
21
14
  equal(sha1(join(tmp, 'lenna.avif')), sha1('tests/fixtures/lenna.avif'))
22
15
  })
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/tests/utils.js ADDED
@@ -0,0 +1,6 @@
1
+ import { createHash } from 'node:crypto'
2
+ import { readFileSync } from 'node:fs'
3
+
4
+ export function sha1(filePath) {
5
+ return createHash('sha1').update(readFileSync(filePath)).digest('hex')
6
+ }
@@ -0,0 +1,22 @@
1
+ import { join } from 'node:path'
2
+ import { test } from 'node:test'
3
+ import { equal } from 'node:assert/strict'
4
+ import { tmpdir } from 'node:os'
5
+ import { execSync } from 'node:child_process'
6
+ import { mkdtempSync, cpSync } from 'node:fs'
7
+ import { sha1 } from './utils.js'
8
+
9
+ test('vsplit splits video at multiple time points', () => {
10
+ const tmp = mkdtempSync(join(tmpdir(), 'vsplit-test-'))
11
+
12
+ const inputFile = join(tmp, '60fps.mp4')
13
+ cpSync('tests/fixtures/60fps.mp4', inputFile)
14
+
15
+ execSync(`src/cli.js vsplit 5 10 15 20 25 ${inputFile}`)
16
+
17
+ for (let i = 1; i <= 6; i++) {
18
+ const generatedFile = join(tmp, `60fps_${i}.mp4`)
19
+ const expectedFile = `tests/fixtures/60fps_${i}.mp4`
20
+ equal(sha1(generatedFile), sha1(expectedFile), `60fps_${i}.mp4 hash should match expected`)
21
+ }
22
+ })
@@ -0,0 +1,20 @@
1
+ import { join } from 'node:path'
2
+ import { test } from 'node:test'
3
+ import { equal } from 'node:assert/strict'
4
+ import { tmpdir } from 'node:os'
5
+ import { execSync } from 'node:child_process'
6
+ import { mkdtempSync, cpSync } from 'node:fs'
7
+ import { sha1 } from './utils.js'
8
+
9
+ test('vtrim trims video from start to end time', () => {
10
+ const tmp = mkdtempSync(join(tmpdir(), 'vtrim-test-'))
11
+
12
+ const inputFile = join(tmp, '60fps.mp4')
13
+ cpSync('tests/fixtures/60fps.mp4', inputFile)
14
+
15
+ execSync(`src/cli.js vtrim 5 10 ${inputFile}`)
16
+
17
+ const out = join(tmp, '60fps.trim.mp4')
18
+ const expected = 'tests/fixtures/60fps_2.mp4'
19
+ equal(sha1(out), sha1(expected), 'Trimmed video (5-10s) should match 60fps_2.mp4')
20
+ })