How to stream audio with spring boot
Asked Answered
R

3

7

I want to enable the user to play a sound. My implementation works fine with firefox. On Safari the sound is not played. I verified, that the audio control works in safari with other websites. So, I assume, that I will have to change something in my controller?

Controller:

@RequestMapping(value = "/sound/character/get/{characterId}", method = RequestMethod.GET, produces = {
            MediaType.APPLICATION_OCTET_STREAM_VALUE })
        public ResponseEntity playAudio(HttpServletRequest request,HttpServletResponse response, @PathVariable("characterId") int characterId) throws FileNotFoundException{

        logger.debug("[downloadRecipientFile]");

        de.tki.chinese.entity.Character character = characterRepository.findById(characterId);
        String file = UPLOADED_FOLDER + character.getSoundFile();

        long length = new File(file).length();


        InputStreamResource inputStreamResource = new InputStreamResource( new FileInputStream(file));
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentLength(length);
        httpHeaders.setCacheControl(CacheControl.noCache().getHeaderValue());
        return new ResponseEntity(inputStreamResource, httpHeaders, HttpStatus.OK);
    }

View

        <audio id="voice" controls="">
            <source src="/sound/character/get/2">
        </audio>

Firefox (works fine): Firefox (works fine)

Safari (not working): Safari (not working!)

Rattlesnake answered 7/2, 2019 at 8:57 Comment(0)
E
8

Most players are going to require a controller that supports partial content requests (or byte ranges).

This can be a little tricky to implement so I would suggest using something like the Spring Community Project Spring Content then you don't need to worry about how to implement the controller at all. The concepts and programming model are very similar to Spring Data's that, by looks of it, you are already using.

Assuming you are using Spring Boot (let me know if you are not) then it would look something like this:

pom.xml

<!-- Java API -->
<dependency>
    <groupId>com.github.paulcwarren</groupId>
    <artifactId>content-fs-spring-boot-starter</artifactId>
    <version>0.6.0</version>
</dependency>
<!-- REST API -->
<dependency>
    <groupId>com.github.paulcwarren</groupId>
    <artifactId>spring-content-rest-boot-starter</artifactId>
    <version>0.6.0</version>
</dependency>

SpringBootApplication.java

@SpringBootApplication
public class YourSpringBootApplication {

  public static void main(String[] args) {
    SpringApplication.run(YourSpringBootApplication.class, args);
  }

  @Configuration
  @EnableFilesystemStores
  public static class StorageConfig {
    File filesystemRoot() {
        return new File("/path/to/your/sounds");
    }

    @Bean
    public FileSystemResourceLoader fsResourceLoader() throws Exception {
      return new FileSystemResourceLoader(filesystemRoot().getAbsolutePath());
    }
  }

  @StoreRestResource(path="characterSounds")
  public interface SoundsContentStore extends ContentStore<UUUID,String> {
    //
  }
}

Charater.java

public class Character {

    @Id
    @GeneratedValue
    private Long id;

    ...other existing fields...

    @ContentId
    private UUID contentId;

    @ContentLength
    private Long contnetLength;

    @MimeType
    private String mimeType;
} 

This is all you need to create a REST-based audio service at /characterSounds supporting streaming. It actually supports full CRUD functionality as well; Create == POST, Read == GET (include the byte-range support that you need), Update == PUT, Delete == DELETE in case that is useful to you. Uploaded sounds will be stored in "/path/to/your/sounds".

So...

GET /characterSounds/{characterId}

will return a partial content response and this should stream properly in most, if not all, players (including seeking forwards and backwards).

HTH

Elemental answered 7/2, 2019 at 16:38 Comment(0)
R
0

Another solution (and for me easy to implement with only minor changes to my existing code) is here:

https://github.com/spring-projects/spring-framework/blob/v4.2.0.RC1/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java#L463

Rattlesnake answered 10/2, 2019 at 11:0 Comment(1)
Spring Content uses that internally @tobi. Glad you got something working.Elemental
R
-2

you can use this code in java

void sound(String path) {
    File lol = new File(path);
    try {
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(lol));
        clip.start();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Ricardo answered 20/1, 2022 at 11:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.