Sopare precision and accuracy

Whoa, it’s about time to talk about accuracy and precision in terms of SOPARE. SOPARE is a Python project that listens to microphone input and makes predictions from trained sounds like spoken words. Offline and in real time.

Before we go into the details we make a quick excursion how SOPARE is processing sound. The microphone listens permanent and records every sound in small chunks. As soon as the volume of a sound reaches a specified threshold, SOPARE adds some small chunks and creates a bigger chunk. At this time, SOPARE has an array of data in raw mic input format. The input receives some filtering (HANNING) and the time domain data is transformed into the frequency domain. Now SOPARE removes unused frequencies as specified in the configuration (LOW_FREQ and HIGH_FREQ).

At this stage SOPARE is able to compress the data (MIN_PROGRESSIVE_STEP, MAX_PROGRESSIVE_STEP). Compression is a big factor of precision. Progressive steps mean that a number of frequencies are combined into one value. A progressive step of 100 takes 100 values and creates one (1) combined value. This is a very rough preparation and a good way to create lots of false positives. The opposite would be a step of one (1) which would use each frequency for the characteristic and prediction and represents the max. accuracy – but maybe also the worst true positive recognition.

This is how the process looks like. From the full blown time domain data (40000), to the specified number of frequencies (600) and at the end there is a compressed set of data (24) which is quite clear and used for the predictions.



You need to test around and find some good values for your setup and environment. If you have optimal values, train your sound patterns.

Please note that the values in the section „Stream prep and silence configuration options“ must be used for training and whenever you change them you need to do a new training round. This means remove the trained files via

mv dict/*.raw /backup


rm dict/*.raw

and train again!

Now let’s talk about options to enhance precision and accuracy. First of all, you should note that one identifier is always susceptible for false positives. Checking for two or more patterns/words increase the precision big time.

The second option is to make use of the config options to increase the accuracy. Let’s start with the one that identifies a word or pattern:


The marginal value can have a range between 0 and 1. Zero (0) means that everything will be identified as the beginning of a word, 1 means that the trained sample and the current sound must match 100%. Good values lie between between 0.7 and 0.9. Test around how high you can increase the value while still getting real results. For testing purpose keep this value quite low.


is the option that is used for comparison. Again, 0 means everything is a match and 1 means that the trained pattern and the current sound must match 100%. For one word scenarios, this value can be quite high, two or more words require normally lower values as the transitions from two patterns are most likely not as single trained words. Good values in my setups are between 0.6 and 0.9. 0.9 for single words, lower values for multiple word recognition.

The following values have a huge impact but I can’t hand out best case values. Instead, they require some manual testing and adjustment:


These values are somehow special. For each word/pattern SOPARE calculates the distance from the trained word and the current sound. A low distance means that the characteristic is similar, high distances means that there is a difference. Left and right means that the frequency ranges are halved and the lower and higher bandwidth is compared respectively. Even if a prediction for the whole word is very close, even a small distance can be essential to filter out false positives. The debug option reveals the most important values:


Again, this requires some fiddling around to find the optimal values that gives true positive and avoid the false ones…start with high values and reduce until you are satisfied. In my smart home light control setup the values are around 0.3 and my false positive rate is near zero although SOPARE is running 24/7 and my house is quite noisy (kids, wife, …).

The last config options to consider is the calculation basis for the value „MIN_CROSS_SIMILARITY“. The sum of the three following values should be 1:


„SIMILARITY_NORM“ is the comparison of the FFT similarity.

„SIMILARITY_HEIGHT“ compares against the time domain shape. Good if you want to consider a certain volume.

„SIMILARITY_DOMINANT_FREQUENCY“ is the similarity factor for the dominant frequency (f0).

I recommend to play around with this values and learn the impacts. Based on the environment, sound and the desired outcome there are plenty of possible combinations. Here are some examples:

Puuhhh, this post got longer than expected and the videos have also 25 minutes content. Hope I got everything covered:

Part 1:

Part 2:

Part 3:

Part 4:


That’s it. If you have questions or comments don’t keep back and let me know 😉

As always, have fun and happy voice controlling 😉

20 thoughts on “Sopare precision and accuracy

  1. Hi,

    I’m trying to adjust SOPARE for detecting door knock pattern – if someone knocked 2x or 3x times.

    Scenario is like this:
    – Train SOPARE with two patterns ( -t 2xknock & -t 3xknock)
    – compile and then loop
    – whenever THRESHOLD value is detected listen for pattern until silent for max1sec
    – compare recorded audio with 2xknock and 3xknock patterns
    – printout if something is detected.

    This would be very smart detection of knocks. There are many tutorials for detecting knocks on RPI, but they all look only for threshold level and detect knock on every noise that is loud enough.

    It all sounds good in theory, but I’m still having problems to get it work. I thought it would maybe help someone if I describe my findings.

    Problem 1
    1. I train Sopart with „-t 3xknock“ (where I knock 3 times) & then compile it
    2. When I go to loop mode 3xknock is detected even if i knock only once

    I guess solution would be to set correct timing – so that while training it would actually capture all three knocks and then also listen to all three.

    Any suggestion how to set training time so that it will capture all three knocks?
    Any suggestion how to listen for 3 knocks in loop mode?

    Pattern with 3 knocks is ~1sec long. This well below MAX_TIME = 3.5 defined in config.

    Problem 2
    I recorded wav of knocks on rpi and then open it on Adobe Audition CC.
    I was experimenting with equaliser to filter out other noises.
    I found out that if I remove frequencies from 0-500Hz & 2kHz all noises are removed and what is left are pretty much only knocks.

    When I try to apply this filter to Sopart by setting:
    LOW_FREQ = 500
    HIGH_FREQ = 2000

    I get very strange error on loop after first THRESHOLD is detected:

    Process buffering queue:
    Traceback (most recent call last):
    File „/usr/lib/python2.7/multiprocessing/“, line 258, in _bootstrap
    File „/home/pi/sopare/sopare/“, line 42, in run
    File „/home/pi/sopare/sopare/“, line 82, in check_silence
    self.stop(„stop append mode because of silence“)
    File „/home/pi/sopare/sopare/“, line 53, in stop
    File „/home/pi/sopare/sopare/“, line 93, in force_tokenizer
    self.tokenize([ { ‚token‘: ’start analysis‘, ’silence‘: self.silence, ‚pos‘: self.counter, ‚adapting‘: 0, ‚volume‘: 0, ‚peaks‘: self.peaks } ])
    File „/home/pi/sopare/sopare/“, line 52, in tokenize
    self.filter.filter(self.buffer, meta)
    File „/home/pi/sopare/sopare/“, line 91, in filter
    nam = numpy.amax(nfft)
    File „/usr/lib/python2.7/dist-packages/numpy/core/“, line 2130, in amax
    out=out, keepdims=keepdims)
    File „/usr/lib/python2.7/dist-packages/numpy/core/“, line 17, in _amax
    out=out, keepdims=keepdims)
    ValueError: zero-size array to reduction operation maximum which has no identity

    Sample without filter:

    Sample with filter applied :

    Equaliser settings used for filter:

    What is causing this?
    How to avoid it?

    It only happens if I change LOW_FREQ and HIGH_FREQ …

    Problem 3
    If I use -l -~ to save detected patterns I get many very strange sounding wav-s. They sound very high pitch and are only few ms long. There is also no wav with complete 3x knock pattern. Actually I can not recognise even a simple knock.


    While doing test recording for analysis in Adobe Audition I did it with:
    arecord -D plughw:0,0 -f cd test2.wav

    Why Am I getting high disturbed wav? Is there anything wrong with sound card setting? I’m using USB sound card.

    Thank you for great work,

  2. Hi Gregor.

    Let`s try to get some ground on your issues. First, do the training with verbose mode enabled. This helps you see if something triggers the training before the first knock. It could be the case that the „THRESHOLD“ is so low that training starts before the real event occurs. In addition, play with the „MAX_SILENCE_AFTER_START“ time. If some sound triggers the training before the knock and MAX_SILENCE_AFTER_START is very low, then you may just get some noise instead of the real thing. Training with verbose mode enabled helps you to avoid such false training sets. Make sure to delete false training files (I mean the corresponding raw files in the dict/ directory before compiling the dict).

    Problem 2 could be a bug or the result of empty frequencies/no values. In combination with problem 3, try to increase the „CHUNKS“ in the config file to higher values like 4096 or even 8192. The frequency analysis is called whenever the size of the „CHUNKS“ value is reached. Seems that in your case the input is too small and/or filtered too much as you just get garbage in the single tokens SOPARE is using for the analysis. If the error still occurs I suggest that you open an issue on GitHub.

    Hope that helped. Have fun!

  3. I trained 3 knocks, no special config options or filtering. The issue for SOPARE to recognize the trained 3 knocks was that the timing between the 3 knocks seems to be always different and therefor a true recognition is difficult. You need very low similarity values to get true results. What I did next: I trained 1 knock several times. The 1 knock was easily recognized and knocking 2 times resulted in this:


    You could leverage the short term memory option (set „STM_RETENTION“ to something like 1 seconds) to get a result like this for easier further processing:

    [u’knock‘, u’knock‘]

    Of course very fast knocking missed some knocks in between but nonetheless the knocking was recognized at least once. Hope this gives you some ideas 🙂

    • Hi,

      Thank you for very fast answer.
      It turned out that my mic was a bit of crap. I replaced it with piezo contact mic and it works much better at detecting knocks. I also did tweak based on your youtube tutorial.

      Increasing CHUNKS works – error no longer appears. It how ever works better with out limiting frequencies now that I have another mic.

      Knocks are now detected consistently. Which is perfect.

      There are how ever two additional questions:
      1. If I make many multiple trainings on the same word I get many „stream read error [Errno Input overflowed] -9981“ messages while in loop. When this errors appears detection is not that good.

      2. How to lower time to detect repeatable knocks – if i knock two times very fast than knocks are not detected (I’m using MAX_SILENCE_AFTER_START = 0.4).


      • It’s a pleasure to answer your questions. Great to hear that it works better now.

        The issue „stream read error [Errno Input overflowed] -9981“ is something I also see quite often and it’s an issue that is Pi related. But the issue also appears on other systems. Maybe due to the concurrent use of network interface and USB port we Rasbperry Pi users face this issue more often. The issue means that the input has more data but the data can’t be processed fast enough. This has an impact on precision as one or more chunks of data are missing either in training or in the prediction phase. But the impact is negligible in my opinion as the default 512 bytes are just a fraction of a second. Maybe someday the RasPi USB port gets more bandwidth and throughput…

        The second issue is something I can’t answer in general. One knock takes maybe around 0.4 to 0.7 seconds which means your used value is already very small. Very fast knocks most likely have different sound characteristics and length – maybe a valid solution is to train the common one knock and in addition train the outliers to increase the overall true positives. The only value that affects the time is this one:


        Other than that: try and test around several config options that works best for you, your use cases and the environment you are in.

        Have fun 🙂

  4. Hi bishoph,

    could you be please so kind and give some more examples? E.g how to train sopare with more words than one. Like „Licht an/Licht aus“ Also I did not find out yet how to make sopare executing commands on the shell. I’m not really a coder. I’m fine with bash scripting but thats it. So please, please write a good docu with a lot of examples. Don’t want to see this project going down like Jasper or other great opensource projects. Since Jasper is not useable. I spent like 20 hours of my freetime for exactly nothing. This is kinda frustrating, since as you might know we all don’t have that much freetime to spent in such things.
    So the more examples you can give how to control things (for me in this case: execute scripts/binaries within the bash for controlling my electric sockets(433MHz) the more likely is it that people can easily use your awesome project. Also the benefit would be, the more examples exist, the easier is it to understand the syntax for adapting them for own future projects with sopare. It’s very unlikely that all people who want to use this have the will to learn python from scratch. I am really a friend of RTFM, but for example the documentation of Jasper is that bad, that you have to spent hours to find solutions in different forums, help pages and so on.

    Kind Regards


    P.S I like it that you do videos as well. But actually I’m using a full HD TV. The text is so small in the videos that I have to go very near to the screen that I can see something. And even then its very tiny.

    • Yes, I’ll do more examples and HOWTOs in the future. But as this takes lots of time here is something you can do right now:

      1) Two or more commands
      This is relatively easy. Just train two commands with the train option you already know:
      ./ -t licht
      ./sopare-py -t an
      ./sopare-py -t aus
      Train each command at least 3 times.
      After that, create the dict with
      ./ -c
      The next step is to find the right config for your commands and your trained words. Just follow the examples and HOWTOs from this blog post. Make sure that the overall time in the config (MAX_SILENCE_AFTER_START and MAX_TIME) suites your commands. Also, the parameter LONG_SILENCE is something you find maybe useful as this value finds the emptiness between the commands words (example: licht LONG_SILENCE an). It helps at the beginning to make an artificial pause (not to long!) between the commands. Just test around a bit.

      2) Plugins and execution of bash scripts in Python
      There is no way to enhance/customize SOPARE without some Python code. But here comes a very simple plugin that should give you an idea how easy it is. Just place it in the plugin directory (the structure looks like this: „plugins/light_on_off_example/“

      And here comes the code for the plugin:

      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
      import subprocess
      def run(readable_results, data, rawbuf):
          if (len(readable_results) == 2 and 'licht' in readable_results and readable_results[0] == 'licht'  and ('aus' in readable_results or 'an' in readable_results)):
          # execute bash script:
          # You can even execute the command and provide the arguments readable_results[0] and readable_results[1]
          # See the link below for details:
    ['/path/to/script', readable_results[0], readable_results[1]])

      Please note that I’ve not tested the above code and not checked if this really runs as I just want to give you a broad idea how to write a custom plugin.

      • Thanks a lot! 🙂 I tested the whole night. I also installed raspbian several times and ended up with jessie. Stretch made issues. For example I was able to train, but the not to start with the -l option. It did not recognize any voice command at all after training. For what ever reason.

        Can you recommend a good mic? I saw you’re using the snowball for the lights. Do you think something like Matrix ( will work as well? Or (
        Plan is to put it behind my couch or somewhere else. Not sure if the snowball is capable for this. Actually Im using an old mic of a headset plugged in the usb audio card.

        Since I had also some troubles with using two commands „licht an“ or „licht aus“. within the console sopare shown me only „licht“ and then „an“ or „aus“… Guess I need to play with the values. I just adjusted the script you provided me a bit to do some useless ping.

        Maybe someone whos reading this want to test. in terminal do:
        cd ~ && echo -e ‚#!/bin/bash\nping -c 1‘ > && chmod +x

        #!/usr/bin/env python
        # -*- coding: utf-8 -*-
        import subprocess
        def run(readable_results, data, rawbuf):
        if (len(readable_results) == 1 and ‚licht‘ in readable_results):[‚/home/pi/‘])

        For sure you can start any other script. This was just for testing.


        • You are welcome 🙂

          As I’m using two Snowball mics I can really recommend them for smart home/home automation controlling. Both mics are working 24/7 in large noisy rooms while speaking from different angles and distances. Noisy rooms because I also track my false positive rate which is so to speak not existing for two and three word activation.

          In terms of the Matrix mic: This should work in theory very well as Amazon Alexa/Echo is using something similar for their products and services. Reading their docs, it seems that you can get either one combined channel with all the echos and different sounds or all eight channels with the different sound captures. If this is true then there is the need to do some additional filtering/processing before one can use it with SOPARE.

          If SOPARE recognizes the commands in serial than you can increase the short term memory value: STM_RETENTION
          By increasing and using the short term memory you get the commands together in your plugin if they fit into the STM_RETENTION window.

          Happy voice controlling and have fun 🙂

  5. Hi bishoph,

    I’m making progress with this neat tool. I also bought a snowball mic. This is pretty awesome.

    Btw. you stated out in another comment when we want to train, the training word should start after „start endless recording“ is shown. I don’t see that at all. What I see is:

    ./ -t licht
    sopare 1.4.0
    ALSA lib pcm_dmix.c:1022:(snd_pcm_dmix_open) unable to open slave
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.hdmi
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.hdmi
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.modem
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.modem
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.phoneline
    ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.phoneline
    ALSA lib pcm_dmix.c:1022:(snd_pcm_dmix_open) unable to open slave
    ALSA lib pcm_dmix.c:1022:(snd_pcm_dmix_open) unable to open slave
    Cannot connect to server socket err = No such file or directory
    Cannot connect to server request channel
    jack server is not running or cannot be started

    So in my env I start directly training the words when I see the „jack server is not running…“

    What happens when I do not start directly after I can see this text? Will sopare wait until it gets input of the mic, or will be the silence then used as well?

    By the way. Since I made some progress here. I would like to share my results for the people who want to try basic stuff like me with the lights on/of.

    Needed things
    1. electric socket e.g Brennenstuhl RCS 1000 N Comfort
    2. 433MHz receiver/transceiver e.g
    3. running sopare with trained words
    4. git://
    5. scripts & plugin (for sopare)

    # You might want to put the script in /usr/local/bin/ as you can put in the compiled send binary as well
    # Don’t forget to make the script executable chmod +x
    # Change the code of your e-socket and use it in the script
    if [ $1 == „an“ ]
    send 1
    exit 0
    elif [ $1 == „aus“ ]
    send 0
    exit 0
    exit 0

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    import subprocess

    def run(readable_results, data, rawbuf):
    if (len(readable_results) == 2 and ‚licht‘ in readable_results and readable_results[0] == ‚licht‘ and (‚aus‘ in readable_results[1] or ‚an‘ in readable_results[1])):[‚couchlight‘, readable_results[1]])

    Note: I will continue on this. Like that it’s possible to talk more human like to the sopare instance.

    bishoph do you have any recommendations where to finetune the settings? I already checked your videos, but like said the text of the terminal is that tiny that its hard to follow. 🙂 What I want to do is like that you can say a complete sentence, and sopare will use trigger words of the sentence.
    1. mach/schalte das
    2. du bist ein böser Computer, nun mach das
    2. fahre die Rolläden

    I am still struggling with the settings to make it work that some filling words for a complete sentence can be in between of the trigger words.



    • Since I changed the logging the video is a bit outdated. To see the mentioned text simple change the config option:
      LOGLEVEL = logging.INFO
      Or even better, use the „-v“ option to see whenever SOPARE listens to something. As SOPARE starts after a certain THRESHOLD any loud enough sound can trigger the training and your word comes in later which means you get garbage training upfront and therefore unreliable recommendations/recognition.

      In terms of your struggling: SOPARE starts after a certain TRESHOLD is reached. Let’s say that you say: „HAL, you are a bad computer, turn out the light“. The whole sentence takes maybe around 4 seconds. If you want to process all the words the config option MAX_TIME must match this timeframe. But, as you make natural stops after „HAL“ and „computer“, the analysis breaks this already in parts like:
      1) HAL
      2) you-are-a-bad-computer
      3) turn-out-the-light
      It is possible that some trigger words are detected within the above parts. You need to make sure that SOPARE is able to detect the silence between the words and „tokenize“ is correctly. There are several values affecting this but I would start with LONG_SILENCE. The faster you speak the lower must be the value – but lower values can mess up your learning process and therefore the recognition. I have to admit that the current „tokenizer“ is far from perfect (as written in the readme: „Word separation is not perfect“). You can try to add your logic into the bash script. The bash script receives all recognitions and executes if the trigger words appear in a certain order in a specific time…

      Hope that helps a bit.

      • Hi,

        I’m making more and more progress with this. It’s soo nice. 🙂 Can you tell me please how to filter log messages out?

        WARNING:sopare.recorder:stream read error [Errno Input overflowed] -9981
        WARNING:sopare.recorder:stream read error [Errno Input overflowed] -9981
        WARNING:sopare.recorder:stream read error [Errno Input overflowed] -9981
        WARNING:sopare.recorder:stream read error [Errno Input overflowed] -9981

        Not sure why this happens now again and again but it’s flodding my console and makes everything very confusing.



        • Yeah, this pyaudio issue is annoying and somehow RPi related…I get this on all my RPi systems. Anyway, like I stated before, this issue affects the accuracy at a minimal level – this means the practical effect can be ignored or at least mitigated by using more liberal similarity/distance values.

          To get rid of the messages you need to either turn the log level back to ERROR or you can comment out/remove the lines causing the message in the file sopare/ … maybe in the future I’ll add some individual loglevels for each class for more flexibility. Adding this to my TODO list 😉

          However, it is fantastic to read that you are making progress 🙂

          • bishoph you rock! 🙂

            I’ll try later to filter this out. Because I really don’t need that flooding.
            I have a future request for you. I think this could help all people who will use this for the finetuning.
            In one of the videos I saw that you played with the values for example of

            MIN_LEFT_DISTANCE = 0.5
            MIN_RIGHT_DISTANCE = 0.4

            For finetuning this you started SOPARE with -l -v and checked the values which were shown on the screen. For myelf most of the values don’t tell me anything, since I dont know exactlywhich value reflects the settings in the config file. Is it possible that you can parse that values and make it more user friendly to see this values?

            So my guess is, when you have like three learned words and only one of them has false positives, it would be awesome to see all the values in the log which reflect exactly the settings which can be finetuned. At the moment I am trying by myself to parse the values which are interesting for me to finetune the settings in the config. But due my lack of python knowledge it’s not that easy. So in short: Filter all not needed information of the verbose mode out and show only the values which can be used for finetuning.

            Keep up the good work!



          • Short update: the issue „[Errno Input overflowed] -9981“ should no longer appear with SOPARE version >= 1.4.3. I’ve tested several microphones in combination with Raspian Jessie and Stretch. The conditions to solves this are to use the recommendations from the „python test/“ test class. There is one exception on Raspbian Stretch, where the audio stream fails continuously. For environments where this behavior for whatever reason appears, I’ve added an experimental option to re-create the stream. This works pretty well and is for the time being a workaround until the root cause is known and can be fixed.

  6. ohh damn…. im not very familiar with this wordpress stuff… it cut the code of the bash script

    if [ $1 == „an“ ]
    send „your socket-code“ „socket number“ 1
    exit 0
    elif [ $1 == „aus“ ]
    send „your socket-code“ „socket number“ 0
    exit 0
    exit 0

  7. okay one more correction. it cut the „<" of the examples, too

    1. "HAL" mach/schalte das "Licht" "an/aus"
    2. "HAL" du bist ein böser Computer, nun mach das "Licht" "an/aus"
    2. "HAL" fahre die Rolläden "hoch/runter"

    How can I add code here? like " “ ?

  8. Hi.

    I wrote a small bash script for making the learning process a little bit easier for me. Since I’m having still big issues with the accuracy. I thought I could share the script. Maybe it’s somehow usefull for you folks.
    It’s not perfect for deleting a fautly record, but in my case it fits. Maybe I’ll update the script later. Let’s see



    # define variables #

    # path to

    # set initial counter to vaule of 1

    # set path to dict directory of SOPARE

    # user input
    read -p „Which Word do you want to learn? “ WORD
    read -p „How often do you want to train? “ COUNT

    # latest file function to remove faulty recordings
    latest() { local file latest; for file in „${1:-.}“/*; do [[ $file -nt $latest ]] && latest=$file; done; rm -f — „$latest“;}

    # do the loop #

    while [ $COUNTER -le $COUNT ]
    $SOPARE -v -t $WORD
    read -p „Hit any key to proceed or [r] to remove last faulty record: “ INPUT
    if [ „$INPUT“ = „r“ ]
    latest $DIR
    echo -e „\nRecent faulty file deleted“

    if [ $COUNTER -le $COUNT ]
    echo „Prepare for next record in 5“
    sleep 1
    echo „Prepare for next record in 4“
    sleep 1
    echo „Prepare for next record in 3“
    sleep 1
    echo „Prepare for next record in 2“
    sleep 1
    echo „Prepare for next record in 1“
    sleep 1
    echo „Record done“
    exit 0

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.