build: migrate to dagger
This commit is contained in:
parent
ca54c93b40
commit
1cedd1da8d
8 changed files with 434 additions and 110 deletions
1
.dagger/.gitattributes
vendored
Normal file
1
.dagger/.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/sdk/** linguist-generated
|
||||||
4
.dagger/.gitignore
vendored
Normal file
4
.dagger/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/sdk
|
||||||
|
/**/node_modules/**
|
||||||
|
/**/.pnpm-store/**
|
||||||
|
/.env
|
||||||
7
.dagger/package.json
Normal file
7
.dagger/package.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"typescript": "^5.5.4"
|
||||||
|
},
|
||||||
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||||
|
}
|
||||||
393
.dagger/src/index.ts
Normal file
393
.dagger/src/index.ts
Normal file
|
|
@ -0,0 +1,393 @@
|
||||||
|
/**
|
||||||
|
* A generated module for TestCard functions
|
||||||
|
*
|
||||||
|
* This module has been generated via dagger init and serves as a reference to
|
||||||
|
* basic module structure as you get started with Dagger.
|
||||||
|
*
|
||||||
|
* Two functions have been pre-created. You can modify, delete, or add to them,
|
||||||
|
* as needed. They demonstrate usage of arguments and return types using simple
|
||||||
|
* echo and grep commands. The functions can be called from the dagger CLI or
|
||||||
|
* from one of the SDKs.
|
||||||
|
*
|
||||||
|
* The first line in this comment block is a short description line and the
|
||||||
|
* rest is a long description with more detail on the module's purpose or usage,
|
||||||
|
* if appropriate. All modules should have a short description.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
dag,
|
||||||
|
Container,
|
||||||
|
Directory,
|
||||||
|
File,
|
||||||
|
Secret,
|
||||||
|
object,
|
||||||
|
func,
|
||||||
|
argument,
|
||||||
|
Platform
|
||||||
|
} from '@dagger.io/dagger';
|
||||||
|
|
||||||
|
@object()
|
||||||
|
export class TestCard {
|
||||||
|
// ============ Helpers ============
|
||||||
|
private auxMediaBase(): Container {
|
||||||
|
// Equivalent of Earthly target: aux-media
|
||||||
|
return dag
|
||||||
|
.container()
|
||||||
|
.from('debian:bookworm')
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'apt-get update && apt-get install -y ffmpeg sox && rm -rf /var/lib/apt/lists/*'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private nodeWithBunBase(platform?: Platform): Container {
|
||||||
|
return dag.container({ platform }).from('node:lts').withExec(['npm', 'install', '-g', 'bun']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ site ============
|
||||||
|
/**
|
||||||
|
* Build the website (equivalent to Earthly target `site`).
|
||||||
|
* Returns the built `build/` directory as a Dagger Directory.
|
||||||
|
*/
|
||||||
|
@func()
|
||||||
|
async site(@argument({ defaultPath: '/' }) source: Directory): Promise<Directory> {
|
||||||
|
const assets = await this.assetsGenerated(source);
|
||||||
|
|
||||||
|
const ctr = this.nodeWithBunBase()
|
||||||
|
.withMountedDirectory('/src', source)
|
||||||
|
.withMountedDirectory('/assets-generated', assets)
|
||||||
|
.withWorkdir('/src')
|
||||||
|
.withExec(['bun', 'install', '--frozen-lockfile'])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'mkdir -p /src/assets/generated && cp -a /assets-generated/. /src/assets/generated'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'sh',
|
||||||
|
'-lc',
|
||||||
|
'export VITE_BUILD_DATE=$(date -Iminutes -u | sed "s/+00:00//") && bun x svelte-kit sync && bun run build'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ctr.directory('/src/build');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ deploy ============
|
||||||
|
/**
|
||||||
|
* Deploy the built site via rsync over SSH (equivalent to Earthly target `deploy`).
|
||||||
|
* Provide secrets corresponding to SSH config and target.
|
||||||
|
*/
|
||||||
|
@func()
|
||||||
|
async deploy(
|
||||||
|
sshConfig: Secret,
|
||||||
|
sshUploadKey: Secret,
|
||||||
|
sshKnownHosts: Secret,
|
||||||
|
sshTarget: Secret,
|
||||||
|
@argument({ defaultPath: '/build' }) build: Directory
|
||||||
|
): Promise<string> {
|
||||||
|
const ctr = dag
|
||||||
|
.container()
|
||||||
|
.from('alpine:latest')
|
||||||
|
.withExec(['sh', '-lc', 'apk add --no-cache openssh-client rsync'])
|
||||||
|
.withMountedDirectory('/build', build)
|
||||||
|
.withSecretVariable('SSH_CONFIG', sshConfig)
|
||||||
|
.withSecretVariable('SSH_UPLOAD_KEY', sshUploadKey)
|
||||||
|
.withSecretVariable('SSH_KNOWN_HOSTS', sshKnownHosts)
|
||||||
|
.withSecretVariable('SSH_TARGET', sshTarget)
|
||||||
|
.withExec([
|
||||||
|
'sh',
|
||||||
|
'-lc',
|
||||||
|
'mkdir -p "$HOME/.ssh" && echo "$SSH_CONFIG" > $HOME/.ssh/config && echo "$SSH_UPLOAD_KEY" > $HOME/.ssh/id_rsa && echo "$SSH_KNOWN_HOSTS" > $HOME/.ssh/known_hosts && chmod 600 $HOME/.ssh/*'
|
||||||
|
])
|
||||||
|
.withExec(['sh', '-lc', 'rsync -cvrz --delete /build/ "$SSH_TARGET"']);
|
||||||
|
|
||||||
|
return ctr.stdout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ avsync-video-components ============
|
||||||
|
/**
|
||||||
|
* Render AV sync frames with Bun. Returns the frames directory.
|
||||||
|
* Mirrors the `avsync-video-components` video part.
|
||||||
|
*/
|
||||||
|
@func()
|
||||||
|
async avsyncFrames(
|
||||||
|
fps: number = 60,
|
||||||
|
size: number = 1200,
|
||||||
|
@argument({ defaultPath: '/' }) source: Directory
|
||||||
|
): Promise<Directory> {
|
||||||
|
const ctr = this.nodeWithBunBase()
|
||||||
|
// pptr troubleshooting libs
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'apt-get update && apt-get -y install chromium libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 && rm -rf /var/lib/apt/lists/*'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser && mkdir -p /home/pptruser && chown -R pptruser:pptruser /home/pptruser'
|
||||||
|
])
|
||||||
|
.withUser('pptruser')
|
||||||
|
.withDirectory('/site', source, { owner: 'pptruser', include: ['package.json', 'bun.lock'] })
|
||||||
|
.withWorkdir('/site')
|
||||||
|
.withExec(['bun', 'install', '--frozen-lockfile', '--verbose'])
|
||||||
|
.withEnvVariable('PUPPETEER_EXECUTABLE_PATH', '/usr/bin/chromium')
|
||||||
|
.withEnvVariable('PUPPETEER_SKIP_DOWNLOAD', '1')
|
||||||
|
.withDirectory('/site', source, { owner: 'pptruser' })
|
||||||
|
.withExec([
|
||||||
|
'bun',
|
||||||
|
'av:render:video',
|
||||||
|
'--fps',
|
||||||
|
String(fps),
|
||||||
|
'--cycles',
|
||||||
|
'1',
|
||||||
|
'--size',
|
||||||
|
String(size),
|
||||||
|
'--output',
|
||||||
|
'/var/tmp/frames'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ctr.directory('/var/tmp/frames');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render AV sync audio track with Bun. Returns the WAV track file.
|
||||||
|
* Mirrors the `avsync-video-components` audio part.
|
||||||
|
*/
|
||||||
|
@func()
|
||||||
|
async avsyncTrack(
|
||||||
|
cycles: number = 16,
|
||||||
|
@argument({ defaultPath: '/' }) source: Directory
|
||||||
|
): Promise<File> {
|
||||||
|
const ctr = this.nodeWithBunBase()
|
||||||
|
.withDirectory('/site', source)
|
||||||
|
.withWorkdir('/site')
|
||||||
|
.withExec(['bun', 'install', '--frozen-lockfile'])
|
||||||
|
.withExec([
|
||||||
|
'bun',
|
||||||
|
'av:render:audio',
|
||||||
|
'-i',
|
||||||
|
'beep.wav',
|
||||||
|
'-o',
|
||||||
|
'/var/tmp/track.wav',
|
||||||
|
'--repeats',
|
||||||
|
String(cycles)
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ctr.file('/var/tmp/track.wav');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ avsync-video ============
|
||||||
|
/**
|
||||||
|
* Compose frames and audio track into avsync.webm. Returns the resulting file.
|
||||||
|
* Mirrors the Earthly `avsync-video` target.
|
||||||
|
*/
|
||||||
|
@func()
|
||||||
|
async avsyncVideo(
|
||||||
|
fps: number = 60,
|
||||||
|
cycles: number = 16,
|
||||||
|
@argument({ defaultPath: '/' }) source: Directory
|
||||||
|
): Promise<File> {
|
||||||
|
const frames = await this.avsyncFrames(fps, 1200, source);
|
||||||
|
const track = await this.avsyncTrack(cycles, source);
|
||||||
|
|
||||||
|
const ctr = this.auxMediaBase()
|
||||||
|
.withMountedDirectory('/frames', frames)
|
||||||
|
.withMountedFile('/track.wav', track)
|
||||||
|
.withExec(['sh', '-lc', 'find /frames -type f | sort | sed "s#^#file #" > /frames.txt'])
|
||||||
|
.withEnvVariable('CYCLES', String(cycles))
|
||||||
|
.withExec([
|
||||||
|
'sh',
|
||||||
|
'-lc',
|
||||||
|
'for i in $(seq 1 $CYCLES); do cat /frames.txt >> /final-frames.txt; done'
|
||||||
|
])
|
||||||
|
.withEnvVariable('FPS', String(fps))
|
||||||
|
.withExec([
|
||||||
|
'sh',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -r "$FPS" -f concat -safe 0 -i /final-frames.txt -i /track.wav -c:v libvpx-vp9 -pix_fmt yuva420p -shortest /avsync.webm'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ctr.file('/avsync.webm');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ audio-channel-tracks (WAV) ============
|
||||||
|
/**
|
||||||
|
* Generate stereo/5.1/7.1 WAV channel tracks from assets/audio/channels input.
|
||||||
|
* Mirrors the Earthly `audio-channel-tracks` target.
|
||||||
|
*/
|
||||||
|
@func()
|
||||||
|
async audioChannelTracksWav(@argument({ defaultPath: '/' }) src: Directory): Promise<Directory> {
|
||||||
|
const ctr = this.auxMediaBase()
|
||||||
|
.withMountedDirectory('/raw', src.directory('/assets/audio/channels'))
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'mkdir -p /input /output && cd /raw && for file in *.wav; do sox "$file" "/input/$file" silence 1 0.1 0.1% reverse silence 1 0.1 0.1% reverse; done'
|
||||||
|
])
|
||||||
|
.withWorkdir('/input')
|
||||||
|
.withExec(['bash', '-lc', 'mkdir -p /output/wav/stereo /output/wav/5.1 /output/wav/7.1'])
|
||||||
|
// stereo
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Left.wav -af "pan=stereo|FL=c0" /output/wav/stereo/Left.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Right.wav -af "pan=stereo|FR=c0" /output/wav/stereo/Right.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Center.wav -af "pan=stereo|FL=c0|FR=c0" /output/wav/stereo/Center.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
// 5.1
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Front_Left.wav -af "pan=5.1|FL=c0" /output/wav/5.1/Front_Left.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Front_Right.wav -af "pan=5.1|FR=c0" /output/wav/5.1/Front_Right.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Front_Center.wav -af "pan=5.1|FC=c0" /output/wav/5.1/Front_Center.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Noise.wav -af "pan=5.1|LFE=c0" /output/wav/5.1/LFE_Noise.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Rear_Left.wav -af "pan=5.1|BL=c0" /output/wav/5.1/Rear_Left.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Rear_Right.wav -af "pan=5.1|BR=c0" /output/wav/5.1/Rear_Right.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
// 7.1
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Front_Left.wav -af "pan=7.1|FL=c0" /output/wav/7.1/Front_Left.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Front_Right.wav -af "pan=7.1|FR=c0" /output/wav/7.1/Front_Right.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Front_Center.wav -af "pan=7.1|FC=c0" /output/wav/7.1/Front_Center.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Noise.wav -af "pan=7.1|LFE=c0" /output/wav/7.1/LFE_Noise.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Side_Left.wav -af "pan=7.1|SL=c0" /output/wav/7.1/Side_Left.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Side_Right.wav -af "pan=7.1|SR=c0" /output/wav/7.1/Side_Right.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Rear_Left.wav -af "pan=7.1|BL=c0" /output/wav/7.1/Rear_Left.wav -hide_banner -loglevel error'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'ffmpeg -i Rear_Right.wav -af "pan=7.1|BR=c0" /output/wav/7.1/Rear_Right.wav -hide_banner -loglevel error'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ctr.directory('/output/wav');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ audio-channel-tracks-ogg ============
|
||||||
|
@func()
|
||||||
|
async audioChannelTracksOgg(
|
||||||
|
@argument({ defaultPath: '/' }) source: Directory
|
||||||
|
): Promise<Directory> {
|
||||||
|
const wavDir = await this.audioChannelTracksWav(source);
|
||||||
|
|
||||||
|
const ctr = this.auxMediaBase()
|
||||||
|
.withMountedDirectory('/output/wav', wavDir)
|
||||||
|
.withExec(['bash', '-lc', 'mkdir -p /output/ogg/stereo /output/ogg/5.1 /output/ogg/7.1'])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'for file in /output/wav/stereo/*.wav; do ffmpeg -i "$file" -c:a libvorbis "/output/ogg/stereo/$(basename "$file" .wav).ogg" -hide_banner -loglevel error; done'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'for file in /output/wav/5.1/*.wav; do ffmpeg -i "$file" -c:a libvorbis "/output/ogg/5.1/$(basename "$file" .wav).ogg" -hide_banner -loglevel error; done'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'for file in /output/wav/7.1/*.wav; do ffmpeg -i "$file" -c:a libvorbis "/output/ogg/7.1/$(basename "$file" .wav).ogg" -hide_banner -loglevel error; done'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ctr.directory('/output/ogg');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ audio-channel-tracks-mp3 ============
|
||||||
|
@func()
|
||||||
|
async audioChannelTracksMp3(
|
||||||
|
@argument({ defaultPath: '/' }) source: Directory
|
||||||
|
): Promise<Directory> {
|
||||||
|
const wavDir = await this.audioChannelTracksWav(source);
|
||||||
|
|
||||||
|
const ctr = this.auxMediaBase()
|
||||||
|
.withMountedDirectory('/output/wav', wavDir)
|
||||||
|
.withExec(['bash', '-lc', 'mkdir -p /output/mp3/stereo /output/mp3/5.1 /output/mp3/7.1'])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'for file in /output/wav/stereo/*.wav; do ffmpeg -i "$file" -c:a libmp3lame "/output/mp3/stereo/$(basename "$file" .wav).mp3" -hide_banner -loglevel error; done'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'for file in /output/wav/5.1/*.wav; do ffmpeg -i "$file" -c:a libmp3lame "/output/mp3/5.1/$(basename "$file" .wav).mp3" -hide_banner -loglevel error; done'
|
||||||
|
])
|
||||||
|
.withExec([
|
||||||
|
'bash',
|
||||||
|
'-lc',
|
||||||
|
'for file in /output/wav/7.1/*.wav; do ffmpeg -i "$file" -c:a libmp3lame "/output/mp3/7.1/$(basename "$file" .wav).mp3" -hide_banner -loglevel error; done'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ctr.directory('/output/mp3');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============ assets-generated ============
|
||||||
|
/**
|
||||||
|
* Aggregate generated assets into a directory containing:
|
||||||
|
* - avsync.webm
|
||||||
|
* - audio/ (MP3 variants)
|
||||||
|
*/
|
||||||
|
@func()
|
||||||
|
async assetsGenerated(@argument({ defaultPath: '/' }) source: Directory): Promise<Directory> {
|
||||||
|
const avsync = await this.avsyncVideo(60, 16, source);
|
||||||
|
const audioMp3 = await this.audioChannelTracksMp3(source);
|
||||||
|
|
||||||
|
return dag.directory().withFile('avsync.webm', avsync).withDirectory('audio', audioMp3);
|
||||||
|
}
|
||||||
|
}
|
||||||
13
.dagger/tsconfig.json
Normal file
13
.dagger/tsconfig.json
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"paths": {
|
||||||
|
"@dagger.io/dagger": ["./sdk/index.ts"],
|
||||||
|
"@dagger.io/dagger/telemetry": ["./sdk/telemetry.ts"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
.dagger/yarn.lock
Normal file
8
.dagger/yarn.lock
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
typescript@^5.5.4:
|
||||||
|
version "5.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6"
|
||||||
|
integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==
|
||||||
110
Earthfile
110
Earthfile
|
|
@ -1,110 +0,0 @@
|
||||||
VERSION 0.7
|
|
||||||
FROM node:lts
|
|
||||||
|
|
||||||
site:
|
|
||||||
RUN npm install -g bun
|
|
||||||
COPY package.json bun.lock /site
|
|
||||||
WORKDIR /site
|
|
||||||
RUN bun install --frozen-lockfile
|
|
||||||
COPY --dir src static vite.config.ts tsconfig.json svelte.config.js /site
|
|
||||||
COPY +assets-generated/ /site/assets/generated
|
|
||||||
RUN export VITE_BUILD_DATE=$(date -Iminutes -u | sed 's/+00:00//') && bun x svelte-kit sync && bun run build
|
|
||||||
SAVE ARTIFACT build AS LOCAL build
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
FROM alpine
|
|
||||||
RUN apk add openssh-client rsync
|
|
||||||
RUN --secret SSH_CONFIG --secret SSH_UPLOAD_KEY --secret SSH_KNOWN_HOSTS \
|
|
||||||
mkdir -p $HOME/.ssh && \
|
|
||||||
echo "$SSH_CONFIG" > $HOME/.ssh/config && \
|
|
||||||
echo "$SSH_UPLOAD_KEY" > $HOME/.ssh/id_rsa && \
|
|
||||||
echo "$SSH_KNOWN_HOSTS" > $HOME/.ssh/known_hosts && \
|
|
||||||
chmod 600 $HOME/.ssh/*
|
|
||||||
COPY +site/build /build
|
|
||||||
RUN --secret SSH_TARGET --push rsync -cvrz --delete /build/ $SSH_TARGET
|
|
||||||
|
|
||||||
|
|
||||||
avsync-video-components:
|
|
||||||
FROM --platform=linux/amd64 node:lts
|
|
||||||
# https://pptr.dev/troubleshooting
|
|
||||||
RUN apt-get update && apt-get -y install libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 && rm -rf /var/lib/apt/lists/*
|
|
||||||
RUN npm install -g bun
|
|
||||||
RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser && mkdir /home/pptruser && chown -R pptruser:pptruser /home/pptruser
|
|
||||||
USER pptruser
|
|
||||||
COPY package.json bun.lock /site
|
|
||||||
WORKDIR /site
|
|
||||||
RUN bun install --frozen-lockfile
|
|
||||||
COPY av-sync av-sync
|
|
||||||
ARG FPS=60
|
|
||||||
ARG CYCLES=16
|
|
||||||
ARG SIZE=1200
|
|
||||||
RUN bun av:render:video --fps $FPS --cycles 1 --size $SIZE --output /var/tmp/frames
|
|
||||||
SAVE ARTIFACT /var/tmp/frames
|
|
||||||
RUN bun av:render:audio -i beep.wav -o /var/tmp/track.wav --repeats $CYCLES
|
|
||||||
SAVE ARTIFACT /var/tmp/track.wav
|
|
||||||
|
|
||||||
aux-media:
|
|
||||||
FROM debian:bookworm
|
|
||||||
RUN apt-get update && apt-get install -y ffmpeg sox && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
avsync-video:
|
|
||||||
FROM +aux-media
|
|
||||||
RUN apt-get update && apt-get install -y ffmpeg sox && rm -rf /var/lib/apt/lists/*
|
|
||||||
COPY +avsync-video-components/track.wav /track.wav
|
|
||||||
COPY +avsync-video-components/frames /frames
|
|
||||||
RUN find frames -type f | sort | xargs -I {} sh -c 'echo "file {}" >> /frames.txt'
|
|
||||||
ARG CYCLES=16
|
|
||||||
RUN for i in $(seq 1 $CYCLES); do cat /frames.txt >> /final-frames.txt; done
|
|
||||||
ARG FPS=60
|
|
||||||
RUN ffmpeg -r $FPS -f concat -i /final-frames.txt -i track.wav -c:v libvpx-vp9 -pix_fmt yuva420p -shortest avsync.webm
|
|
||||||
SAVE ARTIFACT avsync.webm
|
|
||||||
|
|
||||||
audio-channel-tracks:
|
|
||||||
FROM +aux-media
|
|
||||||
RUN mkdir -p /input /output
|
|
||||||
COPY assets/audio/channels /raw
|
|
||||||
WORKDIR /raw
|
|
||||||
RUN for file in *.wav; do sox $file /input/$file silence 1 0.1 0.1% reverse silence 1 0.1 0.1% reverse; done
|
|
||||||
WORKDIR /input
|
|
||||||
RUN mkdir -p /output/wav/stereo /output/wav/5.1 /output/wav/7.1
|
|
||||||
RUN ffmpeg -i Left.wav -af "pan=stereo|FL=c0" /output/wav/stereo/Left.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Right.wav -af "pan=stereo|FR=c0" /output/wav/stereo/Right.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Center.wav -af "pan=stereo|FL=c0|FR=c0" /output/wav/stereo/Center.wav -hide_banner -loglevel error && \
|
|
||||||
# 5.1
|
|
||||||
ffmpeg -i Front_Left.wav -af "pan=5.1|FL=c0" /output/wav/5.1/Front_Left.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Front_Right.wav -af "pan=5.1|FR=c0" /output/wav/5.1/Front_Right.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Front_Center.wav -af "pan=5.1|FC=c0" /output/wav/5.1/Front_Center.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Noise.wav -af "pan=5.1|LFE=c0" /output/wav/5.1/LFE_Noise.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Rear_Left.wav -af "pan=5.1|BL=c0" /output/wav/5.1/Rear_Left.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Rear_Right.wav -af "pan=5.1|BR=c0" /output/wav/5.1/Rear_Right.wav -hide_banner -loglevel error && \
|
|
||||||
# 7.1
|
|
||||||
ffmpeg -i Front_Left.wav -af "pan=7.1|FL=c0" /output/wav/7.1/Front_Left.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Front_Right.wav -af "pan=7.1|FR=c0" /output/wav/7.1/Front_Right.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Front_Center.wav -af "pan=7.1|FC=c0" /output/wav/7.1/Front_Center.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Noise.wav -af "pan=7.1|LFE=c0" /output/wav/7.1/LFE_Noise.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Side_Left.wav -af "pan=7.1|SL=c0" /output/wav/7.1/Side_Left.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Side_Right.wav -af "pan=7.1|SR=c0" /output/wav/7.1/Side_Right.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Rear_Left.wav -af "pan=7.1|BL=c0" /output/wav/7.1/Rear_Left.wav -hide_banner -loglevel error && \
|
|
||||||
ffmpeg -i Rear_Right.wav -af "pan=7.1|BR=c0" /output/wav/7.1/Rear_Right.wav -hide_banner -loglevel error
|
|
||||||
SAVE ARTIFACT /output/wav/
|
|
||||||
|
|
||||||
audio-channel-tracks-ogg:
|
|
||||||
FROM +audio-channel-tracks
|
|
||||||
RUN mkdir -p /output/ogg/stereo /output/ogg/5.1 /output/ogg/7.1
|
|
||||||
RUN for file in /output/wav/stereo/*.wav; do ffmpeg -i $file -c:a libvorbis /output/ogg/stereo/$(basename $file .wav).ogg -hide_banner -loglevel error; done && \
|
|
||||||
for file in /output/wav/5.1/*.wav; do ffmpeg -i $file -c:a libvorbis /output/ogg/5.1/$(basename $file .wav).ogg -hide_banner -loglevel error; done && \
|
|
||||||
for file in /output/wav/7.1/*.wav; do ffmpeg -i $file -c:a libvorbis /output/ogg/7.1/$(basename $file .wav).ogg -hide_banner -loglevel error; done
|
|
||||||
SAVE ARTIFACT /output/ogg
|
|
||||||
|
|
||||||
audio-channel-tracks-mp3:
|
|
||||||
FROM +audio-channel-tracks
|
|
||||||
RUN mkdir -p /output/mp3/stereo /output/mp3/5.1 /output/mp3/7.1
|
|
||||||
RUN for file in /output/wav/stereo/*.wav; do ffmpeg -i $file -c:a libmp3lame /output/mp3/stereo/$(basename $file .wav).mp3 -hide_banner -loglevel error; done && \
|
|
||||||
for file in /output/wav/5.1/*.wav; do ffmpeg -i $file -c:a libmp3lame /output/mp3/5.1/$(basename $file .wav).mp3 -hide_banner -loglevel error; done && \
|
|
||||||
for file in /output/wav/7.1/*.wav; do ffmpeg -i $file -c:a libmp3lame /output/mp3/7.1/$(basename $file .wav).mp3 -hide_banner -loglevel error; done
|
|
||||||
SAVE ARTIFACT /output/mp3
|
|
||||||
|
|
||||||
assets-generated:
|
|
||||||
COPY +avsync-video/avsync.webm /assets/avsync.webm
|
|
||||||
COPY +audio-channel-tracks-mp3/mp3 /assets/audio/
|
|
||||||
SAVE ARTIFACT /assets/* AS LOCAL assets/generated/
|
|
||||||
8
dagger.json
Normal file
8
dagger.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "test-card",
|
||||||
|
"engineVersion": "v0.18.19",
|
||||||
|
"sdk": {
|
||||||
|
"source": "typescript"
|
||||||
|
},
|
||||||
|
"source": ".dagger"
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue