From ae94cbc189d5e7dd253c017c810320c031484d38 Mon Sep 17 00:00:00 2001 From: jaredb7 Date: Sat, 1 Apr 2023 21:42:37 +1000 Subject: [PATCH 1/7] Enhancement to allow simultaneous RTSP stream recording Updated birdnet_recording.sh With a functional change around how ffmpeg is used to make use if it's functionality to accept multiple input streams and map each to a output file. Due to the original implementation generating a filename that contain the date/time streams would be writing to the same file - a small change was make each stream go to it's one file with unique filenames. Updated livestream.sh & spectrogram.php The Livestream service would fail if the RTSP stream setting was more than 1 stream (i.e comma separated list of streams) Made some improvements so streaming is possible from any of the URL's, The Spectrogram page received a new control and some Javascript that allows the user to change between streams, the setting gets saved and the livestream service restarted so it uses's the correct stream. This control is not visible if there are no RTSP streams configured By default the livestream service will stream the the first RTSP URL, if the setting is not set or invalid Updated advanced.php With a small GUI change around RTSP steam entry by providing a input field for each URL and a button to add more fields. In the background nothing changes as we use some Javascript to extract the valus entered and fill in the original rtsp_stream value with the correct comma separated string Updated server.py To work with the recording filename changes so that the correct filename is stored in the DB Updated update_birdnet_snippets.sh To support a new setting RTSP_STREAM_TO_LIVESTREAM on the Spectrogram page and in the livestream service --- homepage/style.css | 18 ++++- scripts/advanced.php | 104 +++++++++++++++++++++++++- scripts/birdnet_recording.sh | 30 +++++++- scripts/livestream.sh | 19 ++++- scripts/server.py | 19 ++++- scripts/spectrogram.php | 115 +++++++++++++++++++++++++++-- scripts/update_birdnet_snippets.sh | 4 + 7 files changed, 294 insertions(+), 15 deletions(-) diff --git a/homepage/style.css b/homepage/style.css index bb2ba6f..fff058a 100644 --- a/homepage/style.css +++ b/homepage/style.css @@ -409,8 +409,8 @@ button:hover { } #body::-webkit-scrollbar { -# display:none -#} + /*display:none*/ +} @media screen and (max-width: 1290px) { .column1,.column2,.column3,.column4 { @@ -563,6 +563,11 @@ button:hover { height:25px !important; } +.copyimage-mobile { + width: 16px !important; + height: 16px !important; +} + .relative { position:relative; } @@ -814,6 +819,15 @@ pre#timer.bash { background-color:#9fe29b } +#newrtspstream{ + cursor: pointer; + margin-left: 2px; + height: 5px; + line-height: 5px; + padding: 3px; + background-color: #9fe29b; +} + #ddnewline::before { content: none; } \ No newline at end of file diff --git a/scripts/advanced.php b/scripts/advanced.php index c7081f7..5408fea 100644 --- a/scripts/advanced.php +++ b/scripts/advanced.php @@ -76,6 +76,22 @@ if(isset($_GET['submit'])) { exec('sudo systemctl restart livestream.service'); } } + + if (isset($_GET["rtsp_stream_to_livestream"])) { + $rtsp_stream_selected = trim($_GET["rtsp_stream_to_livestream"]); + + //Setting exists already, see if the value changed + if (strcmp($rtsp_stream_selected, $config['RTSP_STREAM_TO_LIVESTREAM']) !== 0) { + $contents = preg_replace("/RTSP_STREAM_TO_LIVESTREAM=.*/", "RTSP_STREAM_TO_LIVESTREAM=\"$rtsp_stream_selected\"", $contents); + $contents2 = preg_replace("/RTSP_STREAM_TO_LIVESTREAM=.*/", "RTSP_STREAM_TO_LIVESTREAM=\"$rtsp_stream_selected\"", $contents2); + $fh = fopen("/etc/birdnet/birdnet.conf", "w"); + $fh2 = fopen("./scripts/thisrun.txt", "w"); + fwrite($fh, $contents); + fwrite($fh2, $contents2); + sleep(1); + exec("sudo systemctl restart livestream.service"); + } + } if(isset($_GET["overlap"])) { $overlap = $_GET["overlap"]; @@ -269,6 +285,58 @@ if (file_exists('./scripts/thisrun.txt')) { output.innerHTML = this.value; document.getElementById("predictionCount").innerHTML = parseInt((this.value * )/100); } + + //Keep track of how many new input fields were added + var number_of_new_rtsp_urls_added = 0; + //Function to insert new input fields + function addNewrtspInput() { + //Find the placeholder input field + var url_template_element = document.getElementById('rtsp_stream_url_placeholder'); + var new_url_input_template = url_template_element.cloneNode(); + var br_seperator = document.createElement("BR"); + + //Fix up the new element so it's visible, set the style so it's sligned correctly + new_url_input_template.setAttribute("id", "rtsp_stream_url_new_" + number_of_new_rtsp_urls_added); + new_url_input_template.setAttribute("name", "rtsp_stream_new_" + number_of_new_rtsp_urls_added); + new_url_input_template.setAttribute("style", "margin-left: 107px"); + + //Insert the new input field before the button to add new urls + var newrtspstream_button = document.getElementById('newrtspstream_button_container'); + //Insert the new input element before the newrtspstream button + newrtspstream_button.parentNode.insertBefore(new_url_input_template, newrtspstream_button); + //Add a separator before the button + newrtspstream_button.parentNode.insertBefore(br_seperator, newrtspstream_button); + + //Increment the counter + number_of_new_rtsp_urls_added++; + } + + var rtsp_stream_string = ""; + var rtsp_stream_string_array = []; + //Collect all the rtsp urls that have been set, concat them into a single string and set it into the rtsp_stream input field so it gets saved + function collectrtspUrls() { + //Reset the array and string so we don't get duplicates + rtsp_stream_string = ""; + rtsp_stream_string_array = []; + + //Get the inputs by name (which is similar across + var existing_rtsp_stream_urls = document.querySelectorAll('[name^="rtsp_stream_"]'); + //Loop over the result and get the values + for (let i = 0; i < existing_rtsp_stream_urls.length; i++) { + //Only collect results that re not empty and add them to the array + if (existing_rtsp_stream_urls[i].value !== 'undefined' && existing_rtsp_stream_urls[i].value !== "") { + rtsp_stream_string_array.push(existing_rtsp_stream_urls[i].value.trim()); + } + } + + //if the array is not empty, then implode the array joining all the values by a comma + if (rtsp_stream_string_array.length !== 0) { + rtsp_stream_string = rtsp_stream_string_array.join(','); + //Locate the hidden rtsp_stream input field that we'll populate with the full string which will get saved to the config file + var rtsp_stream_input = document.querySelector('[name=rtsp_stream]'); + rtsp_stream_input.setAttribute('value',rtsp_stream_string); + } + }

If a Human is predicted anywhere among the top predictions, the sample will be considered of human origin and no data will be collected. Start with 1% and move up as needed.

@@ -283,9 +351,37 @@ if (file_exists('./scripts/thisrun.txt')) {

Set Channels to the number of channels supported by your sound card. 32 max.

- -
-

If you place an RTSP stream URL here, BirdNET-Pi will use that as its audio source.

+ + + + $stream_url) { + //For the first input keep the element mostly the same as the original but without styling to align it + if ($stream_idx === 0) { + ?> + +
+ + +
+ +
+
+ add
+
+

If you place an RTSP stream URL here, BirdNET-Pi will use that as its audio source. Multiple streams are allowed but may have a impact on rPi performance. Analyze ffmpeg CPU/Memory usage with top or htop if necessary.


Set Recording Length in seconds between 6 and 60. Multiples of 3 are recommended, as BirdNET analyzes in 3-second chunks.

@@ -389,7 +485,7 @@ foreach($formats as $format){



-