2026-06-06 22:09:19 +01:00
|
|
|
# Install
|
|
|
|
|
|
2026-06-14 14:11:59 +01:00
|
|
|
With internet access, Git, dotnet, Node.js, and GNU/Makefile, simply follow these instructions, in order to have the server part installed:
|
2026-06-06 22:09:19 +01:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
git clone https://github.com/pschneider/yavsc.git
|
|
|
|
|
cd yavsc
|
|
|
|
|
dotnet restore
|
2026-06-14 14:11:59 +01:00
|
|
|
npm install # restore front-end dependencies
|
|
|
|
|
npm run build:js # build the JS/CSS bundles into wwwroot
|
2026-06-06 22:09:19 +01:00
|
|
|
cd contrib
|
|
|
|
|
make install
|
|
|
|
|
```
|
2018-11-19 15:46:20 +01:00
|
|
|
|
2026-06-14 14:11:59 +01:00
|
|
|
The front-end bundles (under `src/Yavsc.Org/wwwroot/js/*.bundle.min.js`
|
|
|
|
|
and `src/Yavsc.Org/wwwroot/css/*.min.css`) are produced by `npm run
|
|
|
|
|
build:js` and committed to the repo, so the runtime .NET stack does
|
|
|
|
|
not need a Node toolchain at publish time. Re-run `npm run build:js`
|
|
|
|
|
after editing any of the entry files under `src/Yavsc.Org/wwwroot/js/`
|
|
|
|
|
or any of the `build/*.entry.js` bundle manifests.
|
|
|
|
|
|
2026-06-07 01:11:23 +01:00
|
|
|
About the mobile app,
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd src/PostIt/PostIt.Android
|
|
|
|
|
dotnet publish -c Release
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
and then, install the app, from the `src/PostIt/PostIt.Android/bin/Release/net10.0/PostIt.apk`
|
|
|
|
|
|
|
|
|
|
|
2026-10-18 22:29:03 +01:00
|
|
|
## PostIt.Desktop on Windows (per-user installer)
|
|
|
|
|
|
|
|
|
|
Build prerequisites: the .NET 10 SDK and NSIS 3 (with its standard
|
|
|
|
|
Modern UI 2 includes). From the repository root, publish a self-contained
|
|
|
|
|
Windows x64 application, then package the **entire** publish directory:
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
dotnet publish src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj -c Release -r win-x64 --self-contained true -p:PublishSingleFile=false
|
|
|
|
|
makensis /DAPP_VERSION=1.1.0-estimate.1 contrib/Windows/postit.nsi
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Set `APP_VERSION` to the version of the published application (the
|
|
|
|
|
`Version` property in `PostIt.Desktop.csproj`). NSIS requires this value;
|
|
|
|
|
it is used in the installer filename and Windows' installed-apps list.
|
|
|
|
|
On Linux, use `makensis -DAPP_VERSION=1.1.0-estimate.1 contrib/Windows/postit.nsi`
|
|
|
|
|
instead. Cross-publishing uses the same `dotnet publish` command.
|
|
|
|
|
If `makensis` is not on `PATH` on Windows, invoke the executable from
|
|
|
|
|
the NSIS installation directory.
|
|
|
|
|
|
|
|
|
|
The result is `contrib/Windows/PostIt-<version>-win-x64-Setup.exe`.
|
|
|
|
|
NSIS also accepts `PUBLISH_DIR` (an absolute path to a different
|
|
|
|
|
**win-x64** publish directory) and `OUTPUT_FILE` (the output executable
|
|
|
|
|
path), with the same `/DNAME=value` or `-DNAME=value` syntax. Quote an
|
|
|
|
|
entire define argument when its value contains spaces.
|
|
|
|
|
|
|
|
|
|
The installer does not request elevation or install a shared .NET runtime.
|
|
|
|
|
It installs in `%LOCALAPPDATA%\Yavsc\PostIt.Desktop`, creates a Start menu
|
|
|
|
|
shortcut for the current user and registers `postit://` in
|
|
|
|
|
`HKCU\Software\Classes` so browser-based sign-in returns to PostIt.
|
|
|
|
|
Windows' installed-apps list provides the uninstaller. Close PostIt before
|
|
|
|
|
installing an update or uninstalling it.
|
|
|
|
|
|
|
|
|
|
The `app` subdirectory is reserved for published application files and is
|
|
|
|
|
removed recursively on uninstall. User settings and tokens stored outside
|
|
|
|
|
this directory are preserved. Reinstalling uses the recorded installation
|
|
|
|
|
directory and overwrites the packaged files.
|
|
|
|
|
|
|
|
|
|
The self-contained publication includes .NET, but does **not** add native
|
|
|
|
|
LibVLC libraries: video playback still requires a compatible Windows x64
|
|
|
|
|
LibVLC installation. PostIt reports an unavailable video player and offers
|
|
|
|
|
the system browser as an alternative.
|
|
|
|
|
|
|
|
|
|
Before distributing a release, test installation, startup, the `postit://`
|
|
|
|
|
login callback, updating and uninstallation on Windows with a standard
|
|
|
|
|
(non-administrator) account. Installer compilation alone does not validate
|
|
|
|
|
these Windows runtime behaviours.
|
|
|
|
|
|
2026-10-19 15:22:34 +01:00
|
|
|
## Podcast live broadcasts and replays
|
|
|
|
|
|
|
|
|
|
PostIt Desktop's home page provides **Podcasts : directs et replays**.
|
|
|
|
|
Install LibVLC 3 with the `livehttp`, MPEG-TS, x264 and AAC plugins on the
|
|
|
|
|
Desktop machine. Windows capture uses DirectShow; Linux uses V4L2 and the
|
|
|
|
|
default PulseAudio microphone. FFmpeg is **not** a runtime dependency.
|
|
|
|
|
Select a camera and optionally a microphone, enter a title, then start.
|
|
|
|
|
Stopping publishes the retained replay; navigating away or logging out
|
|
|
|
|
stops capture too. A second signed-in PostIt instance can watch the live
|
|
|
|
|
broadcast while it is being captured.
|
|
|
|
|
|
|
|
|
|
Both upload and playback require a bearer token with the `api` scope.
|
|
|
|
|
All authenticated API users can watch the catalogue, live broadcasts and
|
|
|
|
|
replays; only the broadcaster can upload, complete or delete their podcast.
|
|
|
|
|
Media is not anonymous and no access token is included in a playback URL.
|
|
|
|
|
|
|
|
|
|
Configure Yavsc.Api's `Podcast` section (or environment variables such as
|
|
|
|
|
`Podcast__RootPath`). No database migration or server-side encoder is needed:
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"Podcast": {
|
|
|
|
|
"RootPath": "/srv/yavsc-private/podcasts",
|
|
|
|
|
"MaxSegmentBytes": 8388608,
|
|
|
|
|
"MaxOwnerBytes": 1073741824,
|
|
|
|
|
"MaxSegments": 7200,
|
|
|
|
|
"MaxOwnerPodcasts": 100,
|
|
|
|
|
"IdleTimeoutSeconds": 60
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`RootPath` must be absolute, writable by Yavsc.Api and **outside any static
|
|
|
|
|
file directory**. The default is `DataDir/podcasts` under the API application
|
|
|
|
|
base directory. Use a persistent volume and back up this entire directory
|
|
|
|
|
(indexes and segments together). This implementation supports **one API
|
|
|
|
|
process per storage root**, not multiple writers or replicas.
|
|
|
|
|
|
|
|
|
|
Defaults allow 8 MiB per segment (also the HTTP endpoint's hard limit),
|
|
|
|
|
1 GiB retained per owner, 7,200 segments per episode and 100 episodes per
|
|
|
|
|
owner. At the target two-second segment duration, this is roughly four hours
|
|
|
|
|
per episode; the byte quota can be reached earlier. Podcast quotas are
|
|
|
|
|
separate from the legacy user-files `DiskQuota`. Deleting an ended podcast
|
|
|
|
|
releases its podcast quota. Reverse proxies must allow an 8 MiB PUT body
|
|
|
|
|
and forward Authorization on every API request.
|
|
|
|
|
|
|
|
|
|
A broadcast without a new committed segment for 60 seconds, or present
|
|
|
|
|
when the API restarts, becomes an interrupted replay on the next catalogue,
|
|
|
|
|
manifest or upload request. Already committed media remains playable.
|
|
|
|
|
The broadcaster retries transient upload errors twice using the same
|
|
|
|
|
sequence and content; it stops if capture fails or the pending local media
|
|
|
|
|
exceeds 64 MiB. Unacknowledged media is retained under
|
|
|
|
|
`%LOCALAPPDATA%\PostIt\podcast-capture` (Linux: the corresponding local
|
|
|
|
|
application data directory), with `podcast.json` and the capture playlist
|
|
|
|
|
for manual recovery. There is no automatic resumption after an application
|
|
|
|
|
restart; these private local recordings may be removed manually when no
|
|
|
|
|
longer needed.
|
|
|
|
|
|
|
|
|
|
The replay is **HLS/MPEG-TS**, not an MP4 download. PostIt's authenticated
|
|
|
|
|
player joins a live broadcast up to three segments behind the edge and
|
|
|
|
|
reads a replay from its beginning; seeking is not implemented. Native
|
|
|
|
|
camera/microphone permissions, drivers and codecs must still be verified
|
|
|
|
|
on each target Windows/Linux machine.
|
|
|
|
|
|
2026-10-19 22:18:22 +01:00
|
|
|
### Android podcasts
|
|
|
|
|
|
|
|
|
|
The Android APK bundles LibVLC and uses a native Android video surface inside
|
|
|
|
|
the same Avalonia video page as desktop. Catalogue, playback controls and
|
|
|
|
|
authenticated segment downloads are shared; no external browser, public media
|
|
|
|
|
URL or camera/microphone permissions are needed to watch a podcast.
|
|
|
|
|
|
|
|
|
|
Leaving the app stops playback and cancels downloads. Returning recreates the
|
|
|
|
|
player: a replay starts from the beginning, and a live stream rejoins near the
|
|
|
|
|
live edge. Seeking and background audio are not supported.
|
|
|
|
|
|
|
|
|
|
Broadcasting requires **Android 8 (API 26) or newer**. In the shared podcast
|
|
|
|
|
page, detect devices, select front/rear camera and optionally the microphone,
|
|
|
|
|
then start the live broadcast while PostIt is visible. Camera permission,
|
|
|
|
|
microphone permission when selected, and notification permission on Android 13+
|
|
|
|
|
must be granted. A permission denial is reported in the page without starting
|
|
|
|
|
capture or creating a server broadcast. Permissions are requested before the
|
|
|
|
|
server session is created so a long permission dialog cannot expire it.
|
|
|
|
|
Watching does not request these permissions.
|
|
|
|
|
|
|
|
|
|
Android uses Camera2 and its native MediaRecorder H.264/AAC encoder, up to 480p at 30 fps,
|
|
|
|
|
not the desktop LibVLC camera inputs or software encoders. MPEG-TS is segmented
|
|
|
|
|
at IDR frames, with timestamps used for segment durations. Closed segments
|
|
|
|
|
enter the same ordered upload/retry/quota/replay pipeline as desktop.
|
|
|
|
|
Devices without a supported camera/encoder report a startup error.
|
|
|
|
|
|
|
|
|
|
A camera/microphone foreground service and a partial wake lock maintain the
|
|
|
|
|
broadcast when PostIt is backgrounded or the screen locks. Its ongoing
|
|
|
|
|
notification returns to the app and offers **Arreter et publier**. Stopping
|
|
|
|
|
flushes the final segment before completing the replay. Leaving the podcast
|
|
|
|
|
page or logging out still stops capture. Android's explicit service stop,
|
|
|
|
|
process termination or application restart does not automatically restart a
|
|
|
|
|
camera; segments already received by the server remain available under the
|
|
|
|
|
interrupted-replay rules above. Device power policies can impose additional
|
|
|
|
|
restrictions and must be tested on the intended physical devices.
|
|
|
|
|
|
|
|
|
|
**Native library limitation:** bundled `VideoLAN.LibVLC.Android` 3.6.5 emits
|
|
|
|
|
`XA0141`: its native libraries are not aligned for 16 KiB memory pages.
|
|
|
|
|
Playback on 16 KiB-page devices and store distribution requiring this alignment
|
|
|
|
|
are not validated/supported by this package choice. A compatible native LibVLC
|
|
|
|
|
release is required before claiming that support; a successful APK build or
|
|
|
|
|
a test on a 4 KiB-page emulator does not establish it.
|
|
|
|
|
|
|
|
|
|
Build with the Android workload and SDK configured:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
dotnet build src/PostIt/PostIt.Android/PostIt.Android.csproj
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
On an Android device, verify replay video/audio, live playback, pause/resume,
|
|
|
|
|
rotation, Back navigation and returning after backgrounding the app. Also
|
|
|
|
|
verify an expired session or interrupted network reports a playback error.
|
|
|
|
|
For broadcasting, test front/rear cameras, microphone enabled/disabled,
|
|
|
|
|
permission denial, screen lock, background capture, notification stop and the
|
|
|
|
|
final replay. No automatic retry of a denied permission or a killed camera
|
|
|
|
|
service is performed.
|
|
|
|
|
|
|
|
|
|
The Debug APK includes a local native-capture test activity (excluded from
|
|
|
|
|
Release); it does not create a server podcast. On a dedicated emulator, grant
|
|
|
|
|
camera, audio and notification permissions, then run:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
adb shell am start -W -f 0x18000000 -n fr.pschneider.postit/fr.pschneider.postit.PodcastCaptureTestActivity
|
|
|
|
|
# Wait about 20 seconds for foreground/background recording and final flush.
|
|
|
|
|
adb shell run-as fr.pschneider.postit cat files/podcast-capture-test-result.txt
|
|
|
|
|
# Repeat with the second camera, no audio, and the notification stop action:
|
|
|
|
|
adb shell am start -W -f 0x18000000 -n fr.pschneider.postit/fr.pschneider.postit.PodcastCaptureTestActivity --es microphone false --es camera front --es notificationStop true
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The result reports the segment count, the background progress and the private
|
|
|
|
|
recording directory under `files/podcast-capture-tests`. Recordings remain
|
|
|
|
|
there for local decoder inspection and can be removed after the test.
|
|
|
|
|
|
|
|
|
|
The implementation was checked on an Android 16 x64 emulator with 4 KiB
|
|
|
|
|
pages: camera/microphone capture produced five independently decodable
|
|
|
|
|
H.264/AAC segments across foreground/background operation; the second camera
|
|
|
|
|
without audio produced six decodable H.264 segments, including screen-off
|
|
|
|
|
operation and stop through the notification action. The foreground service
|
|
|
|
|
was gone after both tests. These local tests do not replace an authenticated
|
|
|
|
|
Android-to-server broadcast/replay test or validation on physical devices.
|
|
|
|
|
|
2018-11-19 15:46:20 +01:00
|
|
|
## Resources
|
|
|
|
|
|
2026-06-06 21:58:52 +01:00
|
|
|
System resources needed to install.
|
2018-11-19 15:46:20 +01:00
|
|
|
|
2026-06-06 21:58:52 +01:00
|
|
|
### Some TCP/IP ports to listen
|
|
|
|
|
|
|
|
|
|
The following provided services need all a port to listen :
|
|
|
|
|
|
|
|
|
|
* Org
|
|
|
|
|
* Blogs
|
|
|
|
|
* Api (to become obsolete, in favor of Performer + Client + Com + Moderation )
|
|
|
|
|
|
|
|
|
|
### A Software bloc name
|
|
|
|
|
|
|
|
|
|
In this doc, let's say, `Yavsc`
|
2018-11-19 15:46:20 +01:00
|
|
|
|
|
|
|
|
### A domain name
|
|
|
|
|
|
2022-02-06 03:34:50 +00:00
|
|
|
Wait ... `pschneider.fr`
|
2018-11-19 15:46:20 +01:00
|
|
|
You'll have to see with your provider, in order to power it, and make it point to your host ip, at least concerning the ports 80 & 443.
|
|
|
|
|
|
2025-02-23 21:34:24 +00:00
|
|
|
### A Postgresql db
|
2018-11-19 15:46:20 +01:00
|
|
|
|
2026-06-06 21:58:52 +01:00
|
|
|
The database must be created, and we need its connection string, allowed to modify the data dictionary, see the `.env` file
|
2018-11-19 15:46:20 +01:00
|
|
|
|
2026-06-06 21:58:52 +01:00
|
|
|
### An Smtp mail service
|
2018-11-19 15:46:20 +01:00
|
|
|
|
2026-06-06 21:58:52 +01:00
|
|
|
You'll need to send e-mail ... using smtp and the provider of your choice, see the `.env` file.
|
2018-11-19 15:46:20 +01:00
|
|
|
|
2018-12-11 09:18:38 +00:00
|
|
|
### Google
|
|
|
|
|
|
|
|
|
|
I'll have to make with it, a least a moment, it needs a *service account*, and some setup,
|
|
|
|
|
in the `appsettings.*.json` file, and
|
|
|
|
|
the execution environment variable GOOGLE_APPLICATION_CREDENTIALS to a value pointing the json description file for the Google Service account.
|