How to stream into Freenet / Hyphanet
With version 1489 Freenet / Hyphanet gained a filter for m3u files — playlists — which enables its use as streaming platform.
Update 2021-07: I now created a streaming-website generation tool which automates the process of streaming video-on-demand. It’s called Guile Media Site. You can clone it from sourcehut or get it directly from Freenet:
- https://hg.sr.ht/~arnebab/guile-media-site/browse/site/gms.scm
USK@KxGwMvg~cXm5hs1ZX4NSH~I8fYyqcQD-~8dDdtmDs18,gKSJ4JQ4E1s2Pi-C1iKnfcpWp2pTmcOLaAz6PsogCpw,AQACAAE/watch-36c3-incrementally/13/gms.scm
For streaming audio, use the multi-node version below.
In this article I want to show you how you can forward an arbitrary stream into Hyphanet. To listen to a stream by its USK-key, download and run your own Freenet / Hyphanet node.
TLDR: For audio, just use re-stream to Hyphanet:
cd /tmp && \ git clone https://github.com/hyphanet/re-stream-into-freenet && \ cd re-stream-into-freenet && \ echo -e "\n1\n" | ./re-stream-to-freenet.sh theradiocc \ "http://ogg.theradio.cc/" $(((3 * 24 * 60 * 60))) \ "The Radio.cc: theradio.cc"
Requirements: pyFreenet3 (pip3 install --user pyFreenet3
) and openjdk.
It directly creates a freesite where people can listen to the audio. Watch for output like this:
Creating minimal streaming site: http://127.0.0.1:8888/freenet:USK@fLh9vDtv4yliMDD6tJSb~GMLdC2EQuf~Wpc1PxyFMXo,30P5T9rvQ4UGDJs2hZ7cdzhKYixBgds296gKbfK2XjI,AQACAAE/theradiocc/0/
To embed such a stream on your Freesite, you can use an audio-tag with
the /SSK@.../stream.m3u
in src
. You can simply copy a working tag
from the minimal site.
1. Requirements
Watching this stream requires a Freenet / Hyphanet node running at least build 1492. For uploading the stream you need pyFreenet. And GNU Linux, but you guessed that, right?
- Install Freenet / Hyphanet: install-freenet-linux.html
(as of build 1492, Freenet supports at most openjdk 15. Version 16 and 17 still need module system fixes) - Install pyFreenet: Get Python3, then:
pip3 install --user pyFreenet3
The stream has around 15 minute delay, if your node is fast enough. Given that a practical streaming setup for semi-professional free streaming uses around 20s delay, that’s not too shabby over a confidential decentralized network. With a stronger internet connection, you might be able to push this further down. I’m limited to 40Mbps in theory, the nodes for this use much less.
As source I use theradio.cc, a radio station that streams creativecommons licensed media.
To get gap-less playback for mp3, almost without artefacts, use
mpv --ytdl=no --prefetch-playlist
.
For ogg, use a site in Freenet with an audio-tag, because there’s some issue with our file splitting that trips up mpv playlist playing with ogg.
2. Restreaming theradio.cc with a fully automated script
To use this script, either download it, inspect it, then run it as a bash script, or, if you’re reckless, run it directly:
sudo apt install openjdk-17-jdk wget
pip3 install --user pyFreenet3
wget -O stream-radiocc-into-freenet.sh \
https://www.draketo.de/software/stream-the-radio-cc-into-freenet.txt
bash stream-radiocc-into-freenet.sh
# stream the radio cc (without transcoding) # Select the source: (64k ogg) SOURCE=http://stream.theradio.cc:8000/trcc-stream-lq.ogg # Set the streamtime: 3 days (the maximum time this setup can do is 4 days) STREAMTIME=$(((3 * 24 * 60 * 60))) # Choose a prefix to use for the audio-files in Freenet FILEPREFIX="theradiocc-" FREENET_NODES_BASEFOLDER=$(mktemp -d "${FILEPREFIX}"XXXXXXXX) mkdir "${FREENET_NODES_BASEFOLDER}" cd "${FREENET_NODES_BASEFOLDER}" # following https://www.draketo.de/software/install-freenet-linux.html # use the Lysator mirror, because github throttles us wget http://ftp.lysator.liu.se/pub/freenet/fred-releases/build01494/new_installer_offline_1494.jar \ -O freenet-installer.jar mkdir node1 cd node1 echo === echo follow the prompts echo === java -jar ../freenet-installer.jar -console ./run.sh stop # setting up default settings and restarting cat > freenet.ini <<EOF security-levels.networkThreatLevel=LOW security-levels.physicalThreatLevel=NORMAL fproxy.enableCachingForChkAndSskKeys=true fproxy.hasCompletedWizard=true fproxy.ssl=false fproxy.enabled=true fproxy.port=8180 logger.maxZippedLogsSize=1048 logger.priority=ERROR pluginmanager.loadplugin=Sharesite pluginmanager.enabled=true node.slashdotCacheSize=53687091 node.minDiskFreeShortTerm=536870912 node.uploadAllowedDirs=all node.outputBandwidthLimit=131072 node.storeSize=429496730 node.storeType=ram node.assumeNATed=true node.clientCacheType=ram node.l10n=English node.inputBandwidthLimit=131072 fcp.port=9180 node.opennet.enabled=true node.load.subMaxPingTime=7000 node.load.maxPingTime=15000 End EOF ./run.sh restart echo giving Freenet some time to start sleep 10 echo stop the node to replicate it ./run.sh stop cd "${FREENET_NODES_BASEFOLDER}" # Next just copy the folder: for i in {2..5}; do cp -r node1 node$i; done # Then remove the listen-port lines in freenet.ini. This causes # Freenet to create unique listen ports on the next run. # Also adjust the fcpport, fred port, and the bandwidth for i in {1..5}; do sed -i s/fproxy.port=.*/fproxy.port=8${i}80/ node$i/freenet.ini sed -i s/fcp.port=.*/fcp.port=9${i}80/ node$i/freenet.ini sed -i s/node.listenPort=.*// node$i/freenet.ini sed -i s/node.opennet.listenPort=.*// node$i/freenet.ini sed -i s/node.inputBandwidthLimit=.*/node.inputBandwidthLimit=70k/ node$i/freenet.ini sed -i s/node.outputBandwidthLimit=.*/node.outputBandwidthLimit=70k/ node$i/freenet.ini done # And start them: for i in {1..5}; do cd node$i; ./run.sh start; cd -; done # check the settings. grep -i \\.port node*/*ini # expected: # node1/freenet.ini:fproxy.port=8180 # node1/freenet.ini:fcp.port=9180 # node2/freenet.ini:fproxy.port=8280 # node2/freenet.ini:fcp.port=9280 # node3/freenet.ini:fproxy.port=8380 # node3/freenet.ini:fcp.port=9380 # node4/freenet.ini:fproxy.port=8480 # node4/freenet.ini:fcp.port=9480 # node5/freenet.ini:fproxy.port=8580 # node5/freenet.ini:fcp.port=9580 # Now we have 5 running nodes on FCP ports 9180 to 9580. We‘ll use them to insert # copy ogg data from theradio.cc # first do 10 short segments so people can get in, then create larger segments in the background echo creating the first 10 segments, 5 minutes, before starting to upload. echo Please give them enough time. rm -rf "${FREENET_NODES_BASEFOLDER}"/FREESTREAM-split/ mkdir "${FREENET_NODES_BASEFOLDER}"/FREESTREAM-split/ cd "${FREENET_NODES_BASEFOLDER}"/FREESTREAM-split/ # 30 seconds are 200-300kiB, the ideal size for long-lived files in Freenet timeout 300 nohup ffmpeg -i ${SOURCE} \ -c copy -map 0 \ -segment_time 00:00:30 \ -f segment \ -reset_timestamps 1 "${FILEPREFIX}--%01d.ogg" echo First 10 segments done. Later segments are created in the background. echo This setup can live-stream radio for more than 4 days. # 6 minutes segments are about 2.5MiB each, ensured below 4MiB, # the maximum size for single-container files in Freenet. # This reduces the audible stops in the audio during streaming, # and 6 minute segments are easy to track for humans, # because 10 segments are one hour. This way we can create streams # that you can step in at any hour of the day. timeout ${STREAMTIME} nohup ffmpeg -i ${SOURCE} \ -c copy -map 0 \ -segment_time 00:06:00 \ -f segment \ -reset_timestamps 1 "${FILEPREFIX}%03d.ogg" & KEY=$(fcpgenkey -P 9180 | tail -n 1) PUBKEY=$(fcpinvertkey -P 9180 $KEY) for i in {0..9}; do echo "${FILEPREFIX}--${i}.ogg" >> stream.m3u; done for i in {000..999}; do echo "${FILEPREFIX}${i}.ogg" >> stream.m3u; done # insert stream.m3u with compression because it is large and very # repetitive, and with high priority to ensure that it does not get # drowned by later mp3 inserts # use the last node for the streaming file fcpupload -P 9580 -p 2 ${KEY}stream.m3u stream.m3u # provide the link to the playlist echo Streaming radio to $(fcpinvertkey -P 9180 $KEY)stream.m3u # show how to actually provide the stream as a freesite echo === echo To create a streaming site, open the Sharesite plugin site echo http://localhost:8180/Sharesite/ echo in your browser, click "create a new freesite" echo open your freesite and enter the following: echo 'Stream: <audio src="/'$(fcpinvertkey -P 9180 $KEY)stream.m3u'" controls="controls" style="height: 40px" ></audio>' echo Then change the Insert Hour to -1 to insert at once. echo Save it, go back to the freesite menu, then tick its checkbox and click insert. echo Once a link appears next to your site, your streaming page is ready. You can use that link to share it. echo === echo mpv --ytdl=no --prefetch-playlist http://127.0.0.1:8888/freenet:$(fcpinvertkey -P 9180 $KEY)stream.m3u for i in -- {00..99}; do # upload 9 files in parallel, because Freenet does some checking # for availability, that does not consume much bandwidth but takes # time PRE="${FILEPREFIX}${i}" # wait until the next file is available, to ensure that the current file is ready while test ! -e "${PRE}1.ogg"; do sleep 10; done date # for statistics # upload the first 5 files, one file per insertion-node # the first 5 get higher priority fcpupload -P 9180 -p 2 "${KEY}${PRE}0.ogg" "${PRE}0.ogg" while test ! -e "${PRE}2.ogg"; do sleep 10; done fcpupload -P 9280 -p 2 "${KEY}${PRE}1.ogg" "${PRE}1.ogg" while test ! -e "${PRE}3.ogg"; do sleep 10; done fcpupload -P 9380 -p 2 "${KEY}${PRE}2.ogg" "${PRE}2.ogg" while test ! -e "${PRE}4.ogg"; do sleep 10; done fcpupload -P 9480 -p 2 "${KEY}${PRE}3.ogg" "${PRE}3.ogg" while test ! -e "${PRE}5.ogg"; do sleep 10; done fcpupload -P 9580 -p 2 "${KEY}${PRE}4.ogg" "${PRE}4.ogg" # the next 5 get lower priority so the first finish earlier, # but they run in parallel to catch up on time lost at the end while test ! -e "${PRE}6.ogg"; do sleep 10; done fcpupload -P 9180 "${KEY}${PRE}5.ogg" "${PRE}5.ogg" & while test ! -e "${PRE}7.ogg"; do sleep 10; done fcpupload -P 9280 "${KEY}${PRE}6.ogg" "${PRE}6.ogg" & while test ! -e "${PRE}8.ogg"; do sleep 10; done fcpupload -P 9380 "${KEY}${PRE}7.ogg" "${PRE}7.ogg" & while test ! -e "${PRE}9.ogg"; do sleep 10; done # wait for completion of the upload before the last upload # as a primitive way to limit parallelism; # no use clogging the node if it cannot keep up fcpupload -w -P 9480 "${KEY}${PRE}8.ogg" "${PRE}8.ogg" # wait a full segment to ensure that the last file actually is ready # (because we do not have the next key yet, so we cannot do nice checking) sleep 360 fcpupload -P 9580 "${KEY}${PRE}9.ogg" "${PRE}9.ogg" done sleep 300 echo All the files are uploading. Stopping the streaming nodes. for i in "${FREENET_NODES_BASEFOLDER}"/node*; do cd $i; ./run.sh stop; cd -; done
3. Background: Stream audio with a single node
To stream live, you need a sufficiently fast connection to upload 350KiB to Freenet in 30s.
On my node this is not real-time yet: It takes around 11 minutes to insert 3 minutes of music.
The following code uses some optimizations: The uploaded segments fit into a single SSK splitfile (around 300KiB) and multiple files are inserted in parallel to reduce the impact of wait times for detecting successful uploads (the first with higher priority to reduce the time until the stream can start). It still has room for improvement, though. It could, for example, use multiple insert-nodes, one per file in a batch, and reducing the batch-size to 5. That might allow pushing the delay down to 2 minutes.
HOST=127.0.0.1 FREDPORT=8888 FCPPORT=9481 KEY=$(fcpgenkey -H $HOST -P $FCPPORT | tail -n 1) PUBKEY=$(fcpinvertkey -H $HOST -P $FCPPORT $KEY) FILEPREFIX="theradiocc-" rm -rf /tmp/FREESTREAM-split/ mkdir /tmp/FREESTREAM-split/ cd /tmp/FREESTREAM-split/ for i in {000..999}; do echo "${FILEPREFIX}${i}.mp3" >> stream.m3u; done # insert stream.m3u with compression because it is large and very # repetitive, and with high priority to ensure that it does not get # drowned by later mp3 inserts fcpupload -H $HOST -P $FCPPORT -p 2 ${KEY}stream.m3u stream.m3u # provide the link to the playlist echo Streaming radio to $(fcpinvertkey -H $HOST -P $FCPPORT $KEY)stream.m3u # run mp3 encoding asynchronously for one hour, re-encode to quality 0 # (lowest quality) so this can work with an OK connection. timeout 60000 nohup ffmpeg -i http://mp3.theradio.cc/ \ -c copy -map 0 \ -segment_time 00:00:20 \ -f segment \ -reset_timestamps 1 "${FILEPREFIX}%03d.mp3" & # show a command how to actually start the stream echo you can listen to the stream with echo mpv --ytdl=no --prefetch-playlist http://$HOST:$FREDPORT/freenet:$(fcpinvertkey -H $HOST -P $FCPPORT $KEY)stream.m3u for i in {00..99}; do # upload 9 files in parallel, because Freenet does some checking # for availability, that does not consume much bandwidth but takes # time # wait until all the next 10 files are available while test ! -e "${FILEPREFIX}${i}9.mp3"; do sleep 10; done # wait for one more file to avoid partial files sleep 30 date # upload the first of the batch with higher priority j=0 fcpupload -H $HOST -P $FCPPORT -p 2 "${KEY}${FILEPREFIX}${i}${j}.mp3" "${FILEPREFIX}${i}${j}.mp3" # upload 8 more files for j in {1..8}; do # insert segments in parallel to reduce the impact of wait times fcpupload -H $HOST -P $FCPPORT "${KEY}${FILEPREFIX}${i}${j}.mp3" "${FILEPREFIX}${i}${j}.mp3" done # wait for the upload of the last one of the batch as primitive limitation for the parallel uploads :-) j=9 fcpupload -w -H $HOST -P $FCPPORT "${KEY}${FILEPREFIX}${i}${j}.mp3" "${FILEPREFIX}${i}${j}.mp3" done
If you have Freenet 1489-pre1 running at port 8888, you can listen in on a test-stream with mpv:
mpv --ytdl=no --prefetch-playlist http://127.0.0.1:8888/freenet:SSK@d8lB5dqTaAt~39aFk6KyMU4cb5y3BEkNWgneouaVq0g,P~pzGxzDr08D7NfzKkKOvRHGf3jXUAr7lavnZfszflc,AQACAAE/stream.m3u
(also works in vlc, but with small gaps between the segments)
We have Freenet Radio!
It’s imperfect and you’ll hit some gotchas, but it works, and that’s seriously cool!
4. Background: Multi-node version
To speed this up more, you can install multiple nodes. This recipe can livestream audio over Freenet with 5-10 minutes delay if you have at least 400kiB/s upload speed.
First install a template node:
FREENET_NODES_BASEFOLDER=/tmp/freenet-streaming-nodes mkdir "${FREENET_NODES_BASEFOLDER}" cd "${FREENET_NODES_BASEFOLDER}" mkdir node1 cd node1 # following https://www.draketo.de/software/install-freenet-linux.html wget 'https://github.com/freenet/fred/releases/download/build01492/new_installer_offline_1492.jar' java -jar new_installer_offline_1492.jar -console
follow the prompts, then open the Freenet web interface:
lynx 127.0.0.1:8888 # follow the wizard
Now stop the node:
cd "${FREENET_NODES_BASEFOLDER}"/node1; ./run.sh stop; cd "${FREENET_NODES_BASEFOLDER}"
Next just copy the folder:
for i in {2..5}; do cp -r node1 node$i; done
Then remove the listen-port lines in freenet.ini
. This causes
Freenet to create unique listen ports on the next run.
Also adjust the fcpport, fred port, and optionally the bandwidth:
for i in {1..5}; do sed -i s/fproxy.port=.*/fproxy.port=8${i}80/ node$i/freenet.ini sed -i s/fcp.port=.*/fcp.port=9${i}80/ node$i/freenet.ini sed -i s/node.listenPort=.*// node$i/freenet.ini sed -i s/node.opennet.listenPort=.*// node$i/freenet.ini sed -i s/node.inputBandwidthLimit=.*/node.inputBandwidthLimit=70k/ node$i/freenet.ini sed -i s/node.outputBandwidthLimit=.*/node.outputBandwidthLimit=70k/ node$i/freenet.ini done
And start them:
for i in {1..5}; do cd node$i; ./run.sh start; cd -; done
$ grep -i \\.port node*/*ini
node1/freenet.ini:fproxy.port=8180
node1/freenet.ini:fcp.port=9180
node2/freenet.ini:fproxy.port=8280
node2/freenet.ini:fcp.port=9280
node3/freenet.ini:fproxy.port=8380
node3/freenet.ini:fcp.port=9380
node4/freenet.ini:fproxy.port=8480
node4/freenet.ini:fcp.port=9480
node5/freenet.ini:fproxy.port=8580
node5/freenet.ini:fcp.port=9580
Now we have 5 running nodes on FCP ports 9180 to 9580. We‘ll use them to insert:
# stream the radio cc without transcoding # SOURCE=http://mp3.theradio.cc/ # stream rc3 (remote chaos experience) # SOURCE=https://cdn.c3voc.de/hls/chaoszone/native_sd.m3u8 # stream the radio CC with transcoding # (using ogg instead of opus, because with opus ffmpeg stopped transcoding randomly) SOURCE=http://stream.theradio.cc:8000/trcc-stream-lq.ogg KEY=$(fcpgenkey -P 9180 | tail -n 1) PUBKEY=$(fcpinvertkey -P 9180 $KEY) FILEPREFIX="theradiocc-" rm -rf /tmp/FREESTREAM-split/ mkdir /tmp/FREESTREAM-split/ cd /tmp/FREESTREAM-split/ for i in {000..999}; do echo "${FILEPREFIX}${i}.mp3" >> stream.m3u; done # insert stream.m3u with compression because it is large and very # repetitive, and with high priority to ensure that it does not get # drowned by later mp3 inserts # use the last node for the streaming file fcpupload -P 9580 -p 2 ${KEY}stream.m3u stream.m3u # provide the link to the playlist echo Streaming radio to $(fcpinvertkey -P 9180 $KEY)stream.m3u # run mp3 encoding asynchronously for one hour, re-encode to quality 8 # (second to lowest quality) so this can work with an OK connection. # copy mp3 data from theradio.cc # timeout 60000 nohup ffmpeg -i ${SOURCE} \ # -c copy -map 0 \ # -segment_time 00:00:20 \ # -f segment \ # -reset_timestamps 1 "${FILEPREFIX}%03d.mp3" & # re-encode for 50000 seconds, for 1000 segments, each 50s timeout 50000 nohup ffmpeg -i ${SOURCE} \ -c:a libmp3lame -vn -map 0:a:0 \ -abr 1 -b:a 50k \ -segment_time 00:00:50 \ -f segment \ -reset_timestamps 1 "${FILEPREFIX}%03d.mp3" & # show a command how to actually start the stream echo you can listen to the stream with echo mpv --ytdl=no --prefetch-playlist http://127.0.0.1:8888/freenet:$(fcpinvertkey -P 9180 $KEY)stream.m3u for i in {00..99}; do # upload 9 files in parallel, because Freenet does some checking # for availability, that does not consume much bandwidth but takes # time PRE="${FILEPREFIX}${i}" # wait until the next file is available, to ensure that the current file is ready while test ! -e "${PRE}1.mp3"; do sleep 10; done date # for statistics # upload the first 5 files, one file per insertion-node # the first 5 get higher priority fcpupload -P 9180 -p 2 "${KEY}${PRE}0.mp3" "${PRE}0.mp3" while test ! -e "${PRE}2.mp3"; do sleep 10; done fcpupload -P 9280 -p 2 "${KEY}${PRE}1.mp3" "${PRE}1.mp3" while test ! -e "${PRE}3.mp3"; do sleep 10; done fcpupload -P 9380 -p 2 "${KEY}${PRE}2.mp3" "${PRE}2.mp3" while test ! -e "${PRE}4.mp3"; do sleep 10; done fcpupload -P 9480 -p 2 "${KEY}${PRE}3.mp3" "${PRE}3.mp3" while test ! -e "${PRE}5.mp3"; do sleep 10; done fcpupload -P 9580 -p 2 "${KEY}${PRE}4.mp3" "${PRE}4.mp3" # the next 5 get lower priority so the first finish earlier, # but they run in parallel to catch up on time lost at the end while test ! -e "${PRE}6.mp3"; do sleep 10; done fcpupload -P 9180 "${KEY}${PRE}5.mp3" "${PRE}5.mp3" & while test ! -e "${PRE}7.mp3"; do sleep 10; done fcpupload -P 9280 "${KEY}${PRE}6.mp3" "${PRE}6.mp3" & while test ! -e "${PRE}8.mp3"; do sleep 10; done fcpupload -P 9380 "${KEY}${PRE}7.mp3" "${PRE}7.mp3" & while test ! -e "${PRE}9.mp3"; do sleep 10; done # wait for completion of the upload before the last upload # as a primitive way to limit parallelism; # no use clogging the node if it cannot keep up fcpupload -w -P 9480 "${KEY}${PRE}8.mp3" "${PRE}8.mp3" # wait a full segment to ensure that the last file actually is ready # (because we do not have the next key yet, so we cannot do nice checking) sleep 50 fcpupload -P 9580 "${KEY}${PRE}9.mp3" "${PRE}9.mp3" done
5. Video-Streaming
Wouldn’t it be great to replace youtube with fully decentralized streaming? Can Freenet do it? Are you up for the test? :-)
You won’t be live-streaming yet, bandwidth does not suffice with the currently supported codecs, but you can provide video that starts playing right-away.
We’ll prepare the nodes just like before, and choose a video file to stream.
SOURCE=/tmp/36C3_-_Climate_Modelling-Q_ysS7C8IBw.mkv KEY=$(fcpgenkey -P 9180 | tail -n 1) PUBKEY=$(fcpinvertkey -P 9180 $KEY) FILEPREFIX="36c3-climate-" rm -rf /tmp/FREESTREAM-split/ mkdir /tmp/FREESTREAM-split/ cd /tmp/FREESTREAM-split/ for i in {000..999}; do echo "${FILEPREFIX}${i}.ogv" >> stream.m3u; done # insert stream.m3u with compression because it is large and very # repetitive, and with high priority to ensure that it does not get # drowned by later ogv inserts # use the last node for the streaming file fcpupload -P 9580 -p 2 ${KEY}stream.m3u stream.m3u # provide the link to the playlist echo Streaming radio to $(fcpinvertkey -P 9180 $KEY)stream.m3u # run ogv encoding asynchronously for one hour, re-encode to quality 0 # (lowest quality) so this can work with an OK connection. timeout 60000 nohup ffmpeg -i ${SOURCE} \ -c:v libtheora -c:a libvorbis -map 0 \ -q:v 1 -q:a 1 \ -vf scale=640:480 \ -segment_time 00:00:15 \ -f segment \ -reset_timestamps 1 "${FILEPREFIX}%03d.ogv" & # show a command how to actually start the stream echo you can listen to the stream with echo mpv --ytdl=no --prefetch-playlist http://127.0.0.1:8888/freenet:$(fcpinvertkey -P 9180 $KEY)stream.m3u for i in {00..99}; do # upload 9 files in parallel, because Freenet does some checking # for availability, that does not consume much bandwidth but takes # time PRE="${FILEPREFIX}${i}" # wait until the first 5 files are available while test ! -e "${PRE}5.ogv"; do sleep 10; done date # for statistics # upload the first 5 files, one file per insertion-node # the first 5 get higher priority fcpupload -P 9180 -p 2 "${KEY}${PRE}0.ogv" "${PRE}0.ogv" fcpupload -P 9280 -p 2 "${KEY}${PRE}1.ogv" "${PRE}1.ogv" fcpupload -P 9380 -p 2 "${KEY}${PRE}2.ogv" "${PRE}2.ogv" fcpupload -P 9480 -p 2 "${KEY}${PRE}3.ogv" "${PRE}3.ogv" fcpupload -P 9580 -p 2 "${KEY}${PRE}4.ogv" "${PRE}4.ogv" # wait until the next 5 files are available while test ! -e "${PRE}9.ogv"; do sleep 10; done # wait some more to avoid partial files sleep 60 fcpupload -P 9180 "${KEY}${PRE}5.ogv" "${PRE}5.ogv" fcpupload -P 9280 "${KEY}${PRE}6.ogv" "${PRE}6.ogv" fcpupload -P 9380 "${KEY}${PRE}7.ogv" "${PRE}7.ogv" fcpupload -P 9480 "${KEY}${PRE}8.ogv" "${PRE}8.ogv" # wait for completion of the last upload as a primitive way to limit parallelism fcpupload -w -P 9580 "${KEY}${PRE}9.ogv" "${PRE}9.ogv" done
This has some glitches at the beginning, but you can already watch it:
mpv --ytdl=no --prefetch-playlist http://127.0.0.1:8888/freenet:SSK@I3yBAkjMtFmZPQS088ch7JkIVQzXiwGSEDHy7ge-pds,ahgVpCwvDfOPYB9tTNFS~nSQUS4SjrXaXfEHn999cs4,AQACAAE/stream.m3u
And with that we have video-streaming over Freenet!
6. Background: Split a video file by silence
Depending on your player, playback might not be completely gapless. You can lessen this problem by splitting the video file by silence. While this will likely fail catastrophically for music, it should work pretty well for recorded talks.
Here’s a one-line example from Vi at Stackoverflow, adapted to prouce scaled down ogg theora for Freenet, splitting at places with at least 0.3 seconds of -40dB signal:
ffmpeg -i infile.mkv -filter_complex "[0:a]silencedetect=n=-40dB:d=0.3[outa]" -map [outa] -f s16le -y /dev/null |& F='-q:v 0 -q:a 0 -vf scale=320:240' perl -ne 'INIT { $ss=0; $se=0; } if (/silence_start: (\S+)/) { $ss=$1; $ctr+=1; printf "ffmpeg -nostdin -i infile.mkv -ss %f -t %f $ENV{F} -y ssf-%03d.ogv\n", $se, ($ss-$se), $ctr; } if (/silence_end: (\S+)/) { $se=$1; } END { printf "ffmpeg -nostdin -i infile.mkv -ss %f $ENV{F} -y ssf-%03d.ogv\n", $se, $ctr+1; }' | bash -x